[vlc-commits] codecs: add ATSC A65 helpers
Francois Cartegnie
git at videolan.org
Sun Jan 24 01:24:21 CET 2016
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Jan 22 22:38:40 2016 +0100| [164ef9f2589619cd84d6b30ac78a6fadd4c98c63] | committer: Francois Cartegnie
codecs: add ATSC A65 helpers
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=164ef9f2589619cd84d6b30ac78a6fadd4c98c63
---
modules/codec/atsc_a65.c | 244 ++++++++++++++++++++++++++++++++++++++++++++++
modules/codec/atsc_a65.h | 29 ++++++
2 files changed, 273 insertions(+)
diff --git a/modules/codec/atsc_a65.c b/modules/codec/atsc_a65.c
new file mode 100644
index 0000000..081bd7f
--- /dev/null
+++ b/modules/codec/atsc_a65.c
@@ -0,0 +1,244 @@
+/*****************************************************************************
+ * atsc_a65.c : ATSC A65 decoding helpers
+ *****************************************************************************
+ * Copyright (C) 2016 - VideoLAN Authors
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_charset.h>
+
+#include "atsc_a65.h"
+
+enum
+{
+ ATSC_A65_COMPRESSION_NONE = 0x00,
+ ATSC_A65_COMPRESSION_HUFFMAN_C4C5 = 0x01,
+ ATSC_A65_COMPRESSION_HUFFMAN_C6C7 = 0x02,
+ ATSC_A65_COMPRESSION_RESERVED_FIRST = 0x03,
+ ATSC_A65_COMPRESSION_RESERVED_LAST = 0xAF,
+ ATSC_A65_COMPRESSION_OTHER_FIRST = 0xB0,
+ ATSC_A65_COMPRESSION_OTHER_LAST = 0xFF,
+};
+
+enum
+{
+ ATSC_A65_MODE_UNICODE_RANGE_START = 0x00, /* See reserved ranges */
+ ATSC_A65_MODE_UNICODE_RANGE_END = 0x33,
+ ATSC_A65_MODE_SCSU = 0x3E,
+ ATSC_A65_MODE_UNICODE_UTF16 = 0x3F,
+ ATSC_A65_MODE_TAIWAN_FIRST = 0x40,
+ ATSC_A65_MODE_TAIWAN_LAST = 0x41,
+ ATSC_A65_MODE_SOUTH_KOREA = 0x48,
+ ATSC_A65_MODE_OTHER_FIRST = 0xE0,
+ ATSC_A65_MODE_OTHER_LAST = 0xFE,
+ ATSC_A65_MODE_NOT_APPLICABLE = 0xFF,
+};
+
+const uint8_t ATSC_A65_MODE_RESERVED_RANGES[12] = {
+ /* start, end */
+ 0x07, 0x08,
+ 0x11, 0x1F,
+ 0x28, 0x2F,
+ 0x34, 0x3D,
+ 0x42, 0x47,
+ 0x49, 0xDF,
+};
+
+struct atsc_a65_handle_t
+{
+ char *psz_lang;
+ vlc_iconv_t iconv16;
+};
+
+atsc_a65_handle_t *atsc_a65_handle_New( const char *psz_lang )
+{
+ atsc_a65_handle_t *p_handle = malloc( sizeof(*p_handle) );
+ if( p_handle )
+ {
+ if( psz_lang && strlen(psz_lang) > 2 )
+ p_handle->psz_lang = strdup( psz_lang );
+ else
+ p_handle->psz_lang = NULL;
+
+ p_handle->iconv16 = NULL;
+ }
+ return p_handle;
+}
+
+void atsc_a65_handle_Release( atsc_a65_handle_t *p_handle )
+{
+ if( p_handle->iconv16 )
+ vlc_iconv_close( p_handle->iconv16 );
+ free( p_handle->psz_lang );
+ free( p_handle );
+}
+
+static char *enlarge_to16( const uint8_t *p_src, size_t i_src, uint8_t i_prefix )
+{
+ if( i_src == 0 )
+ return NULL;
+
+ char *psz_new = malloc( i_src * 2 + 1 );
+ if( psz_new )
+ {
+ memset( psz_new, i_prefix, i_src * 2 );
+ psz_new[ i_src * 2 ] = 0;
+ while( *p_src )
+ {
+ psz_new[1] = p_src[0];
+ p_src++;
+ psz_new += 2;
+ }
+ }
+ return psz_new;
+}
+
+static bool convert_encoding_set( atsc_a65_handle_t *p_handle,
+ const uint8_t *p_src, size_t i_src,
+ char **ppsz_merg, size_t *pi_mergmin1,
+ uint8_t i_mode )
+{
+ char *psz_dest = *ppsz_merg;
+ size_t i_mergmin1 = *pi_mergmin1;
+ bool b_ret = true;
+
+ /* First exclude reserved ranges */
+ for( unsigned i=0; i<12; i+=2 )
+ {
+ if( i_mode >= ATSC_A65_MODE_RESERVED_RANGES[i] &&
+ i_mode <= ATSC_A65_MODE_RESERVED_RANGES[i+1] )
+ return false;
+ }
+
+ if( i_mode == ATSC_A65_MODE_UNICODE_RANGE_START ) /* Latin 1 */
+ {
+ char *psz_realloc = realloc( psz_dest, i_mergmin1 + i_src + 1 );
+ if( psz_realloc )
+ {
+ psz_realloc[i_mergmin1 + i_src] = 0;
+ memcpy( &psz_realloc[i_mergmin1], p_src, i_src );
+ psz_dest = psz_realloc;
+ i_mergmin1 += i_src;
+ }
+ else return false;
+ }
+ else if( i_mode > ATSC_A65_MODE_UNICODE_RANGE_START && /* 8 range prefix + 8 */
+ i_mode <= ATSC_A65_MODE_UNICODE_RANGE_END )
+ {
+ if( !p_handle->iconv16 )
+ {
+ if ( !(p_handle->iconv16 = vlc_iconv_open("UTF-8", "UCS-2BE")) )
+ return false;
+ }
+ else if ( VLC_ICONV_ERR == vlc_iconv( p_handle->iconv16, NULL, NULL, NULL, NULL ) ) /* reset */
+ {
+ return false;
+ }
+
+ char *psz16 = enlarge_to16( p_src, i_src, i_mode ); /* Maybe we can skip and feed iconv 2 by 2 */
+ if( psz16 )
+ {
+ char *psz_realloc = realloc( psz_dest, i_mergmin1 + (4 * i_src) + 1 );
+ if( psz_realloc )
+ {
+ const char *p_inbuf = psz16;
+ char *p_outbuf = &psz_realloc[i_mergmin1];
+ size_t i_inbuf = i_src * 2;
+ size_t i_outbuf = i_src * 4;
+ b_ret = ( VLC_ICONV_ERR != vlc_iconv( p_handle->iconv16, &p_inbuf, &i_inbuf,
+ &p_outbuf, &i_outbuf ) );
+ psz_dest = psz_realloc;
+ i_mergmin1 += i_outbuf;
+ psz_dest[i_mergmin1] = 0;
+ }
+ free( psz16 );
+ }
+ else return false;
+ }
+ else
+ {
+ /* Unsupported encodings */
+ return false;
+ }
+
+ *ppsz_merg = psz_dest;
+ *pi_mergmin1 = i_mergmin1;
+ return b_ret;
+}
+
+#define BUF_ADVANCE(n) p_buffer += n; i_buffer -= n;
+
+char * atsc_a65_Decode_multiple_string( atsc_a65_handle_t *p_handle, const uint8_t *p_buffer, size_t i_buffer )
+{
+ char *psz_res = NULL;
+ size_t i_resmin1 = 0;
+
+ if( i_buffer < 1 )
+ return NULL;
+
+ uint8_t i_nb = p_buffer[0];
+ BUF_ADVANCE(1);
+
+ for( ; i_nb > 0; i_nb-- )
+ {
+ if( i_buffer < 4 )
+ goto error;
+
+ bool b_skip = ( p_handle->psz_lang && memcmp(p_buffer, p_handle->psz_lang, 3) );
+ BUF_ADVANCE(3);
+
+ uint8_t i_seg = p_buffer[0];
+ BUF_ADVANCE(1);
+ for( ; i_seg > 0; i_seg-- )
+ {
+ if( i_buffer < 3 )
+ goto error;
+
+ const uint8_t i_compression = p_buffer[0];
+ const uint8_t i_mode = p_buffer[1];
+ const uint8_t i_bytes = p_buffer[2];
+ BUF_ADVANCE(3);
+
+ if( i_buffer < i_bytes )
+ goto error;
+
+ if( i_compression != ATSC_A65_COMPRESSION_NONE ) // TBD
+ {
+ b_skip = true;
+ }
+
+ if( !b_skip )
+ {
+ (void) convert_encoding_set( p_handle, p_buffer, i_bytes,
+ &psz_res, &i_resmin1, i_mode );
+ }
+
+ BUF_ADVANCE(i_bytes);
+ }
+ }
+
+ return psz_res;
+
+error:
+ free( psz_res );
+ return NULL;
+}
+
+#undef BUF_ADVANCE
diff --git a/modules/codec/atsc_a65.h b/modules/codec/atsc_a65.h
new file mode 100644
index 0000000..c4866f8
--- /dev/null
+++ b/modules/codec/atsc_a65.h
@@ -0,0 +1,29 @@
+/*****************************************************************************
+ * atsc_a65.h : ATSC A65 decoding helpers
+ *****************************************************************************
+ * Copyright (C) 2016 - VideoLAN Authors
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *****************************************************************************/
+#ifndef VLC_ATSC_A65_H
+#define VLC_ATSC_A65_H
+
+typedef struct atsc_a65_handle_t atsc_a65_handle_t;
+
+atsc_a65_handle_t *atsc_a65_handle_New( const char *psz_lang );
+void atsc_a65_handle_Release( atsc_a65_handle_t * );
+
+char * atsc_a65_Decode_multiple_string( atsc_a65_handle_t *, const uint8_t *, size_t );
+
+#endif
More information about the vlc-commits
mailing list