[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