[MPlayer-dev-eng] [PATCH] Convert UCS-2LE encoded asf tag

Zuxy Meng zuxy.meng at gmail.com
Wed Aug 23 07:32:45 CEST 2006


Hi,

Currently the simple pack_asf_string() in libmpdemux/asfheader.c only
allows single-byte western letters to be converted, messing up CJK
characters. This patch properly converts UCS-2LE encoded asf tags to
the charset that mplayer internally uses, with the help of iconv.

-- 
Zuxy
Beauty is truth,
While truth is beauty.
PGP KeyID: E8555ED6
-------------- next part --------------
Index: libmpdemux/asfheader.c
===================================================================
--- libmpdemux/asfheader.c	???????? 19503??
+++ libmpdemux/asfheader.c	????????????
@@ -9,6 +9,11 @@
 #include "mp_msg.h"
 #include "help_mp.h"
 
+#ifdef USE_ICONV
+extern char* mp_msg_charset;
+#include <iconv.h>
+#endif
+
 #include "stream.h"
 #include "demuxer.h"
 #include "stheader.h"
@@ -62,7 +67,7 @@
 
 
 // the variable string is modify in this function
-void pack_asf_string(char* string, int length) {
+static void pack_asf_string(char* string, int length) {
   int i,j;
   if( string==NULL ) return;
   for( i=0, j=0; i<length && string[i]!='\0'; i+=2, j++) {
@@ -71,9 +76,7 @@
   string[j]='\0';
 }
 
-// the variable string is modify in this function
-void print_asf_string(const char* name, char* string, int length) {
-  pack_asf_string(string, length);
+static void print_asf_string(const char* name, char* string, int length) {
   mp_msg(MSGT_HEADER,MSGL_V,"%s%s\n", name, string);
 }
 
@@ -192,6 +195,36 @@
   return 1;
 }
 
+/* *p_string must be either NULL or a malloc'ed pointer */
+static void ucs2tolocal(char** p_string,
+                        uint16_t const* wstring, size_t srclen)
+{
+#ifdef USE_ICONV
+  iconv_t ucs2iconv;
+  size_t outlen;
+  char* tocode;
+  char* outbuf;
+
+#ifndef MSG_CHARSET
+  tocode = MSG_CHARSET;
+#else
+  tocode = mp_msg_charset;
+#endif
+  ucs2iconv = iconv_open(tocode, "UCS-2LE");
+  if (ucs2iconv != (iconv_t)(-1)) {
+    outlen = srclen * 2 + 1;
+    *p_string = outbuf = realloc(*p_string, outlen);
+    if (outbuf) 
+      iconv(ucs2iconv, &wstring, &srclen, &outbuf, &outlen);
+    iconv_close(ucs2iconv);
+    return;
+  }
+#endif
+  *p_string = realloc(*p_string, srclen);
+  memcpy(*p_string, wstring, srclen);
+  pack_asf_string(*p_string, srclen);
+}
+
 int read_asf_header(demuxer_t *demuxer,struct asf_priv* asf){
   int hdr_len = asf->header.objh.size - sizeof(asf->header);
   char *hdr = NULL;
@@ -207,6 +240,7 @@
   ASF_stream_header_t *streamh;
   uint8_t *buffer;
   int audio_pos=0;
+  char *string=NULL;
 
   if(hdr_len < 0) {
     mp_msg(MSGT_HEADER, MSGL_FATAL, "Header size is too small.\n");
@@ -339,64 +373,64 @@
   pos = find_asf_guid(hdr, asf_content_desc_guid, 0, hdr_len);
   if (pos >= 0) {
         ASF_content_description_t *contenth = (ASF_content_description_t *)&hdr[pos];
-        char *string=NULL;
+        uint16_t* wstring = NULL;
+        size_t wtoclen = 0;
         pos += sizeof(ASF_content_description_t);
         if (pos > hdr_len) goto len_err_out;
 	le2me_ASF_content_description_t(contenth);
 	mp_msg(MSGT_HEADER,MSGL_V,"\n");
         // extract the title
         if( contenth->title_size!=0 ) {
-          string = &hdr[pos];
+          wstring = (uint16_t*)(&hdr[pos]);
           pos += contenth->title_size;
           if (pos > hdr_len) goto len_err_out;
+          ucs2tolocal(&string, wstring, contenth->title_size);
           if( mp_msg_test(MSGT_HEADER,MSGL_V) )
             print_asf_string(" Title: ", string, contenth->title_size);
-	  else
-	    pack_asf_string(string, contenth->title_size);
 	  demux_info_add(demuxer, "name", string);
         }
         // extract the author 
         if( contenth->author_size!=0 ) {
-          string = &hdr[pos];
+          wstring = (uint16_t*)&hdr[pos];
           pos += contenth->author_size;
           if (pos > hdr_len) goto len_err_out;
+          ucs2tolocal(&string, wstring, contenth->title_size);
           if( mp_msg_test(MSGT_HEADER,MSGL_V) )
             print_asf_string(" Author: ", string, contenth->author_size);
-	  else
-	    pack_asf_string(string, contenth->author_size);
 	  demux_info_add(demuxer, "author", string);
         }
         // extract the copyright
         if( contenth->copyright_size!=0 ) {
-          string = &hdr[pos];
+          wstring = (uint16_t*)&hdr[pos];
           pos += contenth->copyright_size;
           if (pos > hdr_len) goto len_err_out;
+          ucs2tolocal(&string, wstring, contenth->title_size);
           if( mp_msg_test(MSGT_HEADER,MSGL_V) )
             print_asf_string(" Copyright: ", string, contenth->copyright_size);
-	  else
-	    pack_asf_string(string, contenth->copyright_size);
 	  demux_info_add(demuxer, "copyright", string);
         }
         // extract the comment
         if( contenth->comment_size!=0 ) {
-          string = &hdr[pos];
+          wstring = (uint16_t*)&hdr[pos];
           pos += contenth->comment_size;
           if (pos > hdr_len) goto len_err_out;
+          ucs2tolocal(&string, wstring, contenth->title_size);
           if( mp_msg_test(MSGT_HEADER,MSGL_V) )
             print_asf_string(" Comment: ", string, contenth->comment_size);
-	  else
-	    pack_asf_string(string, contenth->comment_size);
 	  demux_info_add(demuxer, "comments", string);
         }
         // extract the rating
         if( contenth->rating_size!=0 ) {
-          string = &hdr[pos];
+          wstring = (uint16_t*)&hdr[pos];
           pos += contenth->rating_size;
           if (pos > hdr_len) goto len_err_out;
+          ucs2tolocal(&string, wstring, contenth->title_size);
           if( mp_msg_test(MSGT_HEADER,MSGL_V) )
             print_asf_string(" Rating: ", string, contenth->rating_size);
         }
 	mp_msg(MSGT_HEADER,MSGL_V,"\n");
+        free(string);
+        string = NULL;
   }
   
   // find content header
@@ -500,5 +534,6 @@
 err_out:
   if (hdr) free(hdr);
   if (streams) free(streams);
+  if (string) free(string);
   return 0;
 }


More information about the MPlayer-dev-eng mailing list