[MPlayer-dev-eng] [PATCH] <P Class> tag in sami subtitle files

Kim, Min-Chul mintcherry79 at gmail.com
Wed Jul 22 11:02:38 CEST 2009


hi,

some sami subtitle files have different types of <P Class>, but
mplayer dose not support it.
so i modified the return type of sub_read_file().

Index: gui/interface.c
===================================================================
--- gui/interface.c	(revision 29435)
+++ gui/interface.c	(working copy)
@@ -446,6 +446,7 @@

 void guiLoadSubtitle( char * name )
 {
+ struct sub_data_array *subdata_array;
  if ( guiIntfStruct.Playing == 0 )
   {
    guiIntfStruct.SubtitleChanged=1; //what is this for? (mw)
@@ -477,7 +478,9 @@
  if ( name )
   {
    mp_msg( MSGT_GPLAYER,MSGL_INFO,MSGTR_LoadingSubtitles,name );
-   subdata=sub_read_file( name, guiIntfStruct.FPS );
+   subdata_array=sub_read_file( name, guiIntfStruct.FPS );
+   subdata=subdata_array?subdata_array->subdata[0]:NULL;
+   free(subdata_array);
    if ( !subdata ) mp_msg( MSGT_GPLAYER,MSGL_ERR,MSGTR_CantLoadSub,name );
    sub_name = (malloc(2 * sizeof(char*))); //when mplayer will be restarted
    sub_name[0] = strdup(name);             //sub_name[0] will be read
Index: gui/win32/dialogs.c
===================================================================
--- gui/win32/dialogs.c	(revision 29435)
+++ gui/win32/dialogs.c	(working copy)
@@ -82,8 +82,11 @@

     if (name)
     {
+        struct sub_data_array *subdata_array;
         mp_msg(MSGT_GPLAYER, MSGL_INFO, MSGTR_LoadingSubtitles, name);
-        subdata = sub_read_file(strdup(name), guiIntfStruct.FPS);
+        subdata_array = sub_read_file(strdup(name), guiIntfStruct.FPS);
+        subdata = subdata_array? subdata_array->subdata[0]: NULL;
+        free(subdata_array);
         if (!subdata) mp_msg(MSGT_GPLAYER, MSGL_ERR, MSGTR_CantLoadSub,name);
         sub_name = (malloc(2 * sizeof(char*))); /* when mplayer will
be restarted */
         sub_name[0] = strdup(name);               /* sub_name[0] will
be read */
Index: mplayer.c
===================================================================
--- mplayer.c	(revision 29435)
+++ mplayer.c	(working copy)
@@ -1029,21 +1029,24 @@
 #ifdef CONFIG_ASS
     ass_track_t *asst = 0;
 #endif
+    struct sub_data_array *subd_array;
+    int i;

     if (filename == NULL || mpctx->set_of_sub_size >= MAX_SUBTITLE_FILES) {
 	return;
     }

-    subd = sub_read_file(filename, fps);
+    subd_array = sub_read_file(filename, fps);
+    subd = subd_array? subd_array->subdata[0]: NULL;
 #ifdef CONFIG_ASS
     if (ass_enabled)
 #ifdef CONFIG_ICONV
-        asst = ass_read_file(ass_library, filename, sub_cp);
+        asst = ass_read_file(ass_library, filename, sub_cp);  //
external SSA/ASS subtitle
 #else
         asst = ass_read_file(ass_library, filename, 0);
 #endif
-    if (ass_enabled && subd && !asst)
-        asst = ass_read_subdata(ass_library, subd, fps);
+//    if (ass_enabled && subd && !asst)
+//        asst = ass_read_subdata(ass_library, subd, fps);

     if (!asst && !subd)
 #else
@@ -1054,11 +1057,17 @@

 #ifdef CONFIG_ASS
     if (!asst && !subd) return;
-    mpctx->set_of_ass_tracks[mpctx->set_of_sub_size] = asst;
+    if (asst) { // external SSA/ASS subtitle
+        mpctx->set_of_ass_tracks[mpctx->set_of_sub_size] = asst;
+    } else {
+        for ( i = 0; i < subd_array->count; ++i )
+            mpctx->set_of_ass_tracks[mpctx->set_of_sub_size + i] =
ass_read_subdata(ass_library, subd_array->subdata[i], fps);
+    }
 #else
     if (!subd) return;
 #endif
-    mpctx->set_of_subtitles[mpctx->set_of_sub_size] = subd;
+for ( i = 0; i < subd_array->count; ++i ) {
+    mpctx->set_of_subtitles[mpctx->set_of_sub_size] = subd_array->subdata[i];
     mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FILE_SUB_ID=%d\n",
mpctx->set_of_sub_size);
     mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FILE_SUB_FILENAME=%s\n",
 	   filename_recode(filename));
@@ -1066,6 +1075,8 @@
     mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_AddedSubtitleFile,
mpctx->set_of_sub_size,
 	    filename_recode(filename));
 }
+    free(subd_array);
+}

 // FIXME: if/when the GUI calls this, global sub numbering gets
(potentially) broken.
 void update_set_of_subtitles(void)
Index: subreader.c
===================================================================
--- subreader.c	(revision 29435)
+++ subreader.c	(working copy)
@@ -97,9 +97,9 @@

 static subtitle *sub_read_line_sami(stream_t* st, subtitle *current) {
     static char line[LINE_LEN+1];
-    static char *s = NULL, *slacktime_s;
+    static char *s = NULL, *slacktime_s, *class_s;
     char text[LINE_LEN+1], *p=NULL, *q;
-    int state;
+    int state, i;

     current->lines = current->start = current->end = 0;
     current->alignment = SUB_ALIGNMENT_BOTTOMCENTER;
@@ -140,6 +140,16 @@
 	    continue;

 	case 2: /* find ">" */
+	    class_s = stristr (s, "Class=");
+	    if (class_s) {
+	      class_s += 6;
+	      s = class_s;
+	      for (i = 0; i < 9 && *class_s != '>'; i++, class_s++)
+	        ((struct subtitle_sami *)current)->sub_class[i] = *class_s;
+	      ((struct subtitle_sami *)current)->sub_class[i] = '\0';
+	    } else {
+	      strcpy(((struct subtitle_sami *)current)->sub_class, "NULL");
+            }
 	    if ((s = strchr (s, '>'))) { s++; state = 3; p = text; continue; }
 	    break;

@@ -1331,11 +1341,11 @@
 #undef MAX_GUESS_BUFFER_SIZE
 #endif

-sub_data* sub_read_file (char *filename, float fps) {
+struct sub_data_array* sub_read_file (char *filename, float fps) {
     stream_t* fd;
     int n_max, n_first, i, j, sub_first, sub_orig;
     subtitle *first, *second, *sub, *return_sub;
-    sub_data *subt_data;
+    struct sub_data_array *subt_data_array;
     int uses_time = 0, sub_num = 0, sub_errs = 0;
     struct subreader sr[]=
     {
@@ -1355,7 +1365,18 @@
 	    { sub_read_line_mpl2, NULL, "mpl2" }
     };
     struct subreader *srp;
+    struct result {
+        char sub_class[10];
+        subtitle *subtitles;
+        int sub_num, sub_errs, n_max;
+    } *results;

+    int result_count = 1;
+    int index = 0;
+
+    results = malloc(sizeof(struct result));
+    memset(results, 0, sizeof(struct result));
+
     if(filename==NULL) return NULL; //qnx segfault
     i = 0;
     fd=open_stream (filename, NULL, &i); if (!fd) return NULL;
@@ -1386,8 +1407,9 @@
     }
 #endif

-    sub_num=0;n_max=32;
-    first=malloc(n_max*sizeof(subtitle));
+    sub_num = results[0].sub_num = 0;
+    n_max = results[0].n_max = 32;
+    first = results[0].subtitles = malloc(n_max*sizeof(subtitle));
     if(!first){
 #ifdef CONFIG_ICONV
 	  subcp_close();
@@ -1397,20 +1419,29 @@
     }

 #ifdef CONFIG_SORTSUB
-    sub = malloc(sizeof(subtitle));
+    if ( sub_format == SUB_SAMI ) {
+        sub = malloc(sizeof(struct subtitle_sami)); /* in subfile,
sub should store <p class> */
+    } else {
+        sub = malloc(sizeof(subtitle));
+    }
     //This is to deal with those formats (AQT & Subrip) which define
the end of a subtitle
     //as the beginning of the following
     previous_sub_end = 0;
 #endif
     while(1){
-        if(sub_num>=n_max){
-            n_max+=16;
-            first=realloc(first,n_max*sizeof(subtitle));
+        if(sub_num>=n_max){ /* if sub has not different types of <P
class>, index should be 0 */
+            n_max = results[index].n_max += 16;
+            first = results[index].subtitles =
realloc(results[index].subtitles, n_max*sizeof(subtitle));
         }
 #ifndef CONFIG_SORTSUB
 	sub = &first[sub_num];
 #endif
-	memset(sub, '\0', sizeof(subtitle));
+        if ( sub_format == SUB_SAMI ) {
+            memset(sub, '\0', sizeof(struct subtitle_sami));
+        } else {
+            memset(sub, '\0', sizeof(subtitle));
+        }
+
         sub=srp->read(fd,sub);
         if(!sub) break;   // EOF
 #ifdef CONFIG_ICONV
@@ -1429,6 +1460,30 @@
 	 }
         // Apply any post processing that needs recoding first
         if ((sub!=ERR) && !sub_no_text_pp && srp->post) srp->post(sub);
+
+if ( sub_format == SUB_SAMI ) { /* if different types of <P Class>
are in subfile, index is changed here!! */
+    if ( strlen(results[0].sub_class) == 0 ) {
+        strcpy(results[0].sub_class, ((struct subtitle_sami *)sub)->sub_class);
+//        printf("sami subtitle class no. 0: %s\n", results[0].sub_class);
+    } else { /* add new sami class */
+        for ( index = 0; index < result_count &&
+            strcmp(results[index].sub_class, ((struct subtitle_sami
*)sub)->sub_class);
+            ++index ); /* find new class */
+        if ( index == result_count ) {
+            ++result_count;
+            results = realloc(results, result_count*sizeof(struct result));
+            strcpy(results[index].sub_class, ((struct subtitle_sami
*)sub)->sub_class);
+
+            first = results[index].subtitles = malloc(32*sizeof(subtitle));
+            sub_num = results[index].sub_num = 0;
+            sub_errs = results[index].sub_errs = 0;
+            n_max = results[index].n_max = 32;
+//            printf("sami subtitle class no. %d: %s\n", index,
results[index].sub_class);
+        }
+    }
+}
+
+
 #ifdef CONFIG_SORTSUB
 	if(!sub_num || (first[sub_num - 1].start <= sub->start)){
 	    first[sub_num].start = sub->start;
@@ -1469,9 +1524,14 @@
 	    }
 	}
 #endif
-        if(sub==ERR) ++sub_errs; else ++sub_num; // Error vs. Valid
+        if(sub==ERR) { // Error vs. Valid
+            results[index].sub_errs = ++sub_errs;
+        } else {
+            results[index].sub_num = ++sub_num;
+        }
     }

+    free(sub);
     free_stream(fd);

 #ifdef CONFIG_ICONV
@@ -1695,17 +1755,26 @@

     return_sub = second;
 } else { //if(suboverlap_enabled)
-    adjust_subs_time(first, 6.0, fps, 1, sub_num, uses_time);/*~6 secs AST*/
-    return_sub = first;
+    for (i = 0; i < result_count; ++i) { /* if sub has not different
types of <P class>, result_count should be 1 */
+        first = results[i].subtitles;
+        sub_num = results[i].sub_num;
+        adjust_subs_time(first, 6.0, fps, 1, sub_num, uses_time);/*~6
secs AST*/
+    }
+    return_sub = first = results[0].subtitles;
 }
     if (return_sub == NULL) return NULL;
-    subt_data = malloc(sizeof(sub_data));
-    subt_data->filename = strdup(filename);
-    subt_data->sub_uses_time = uses_time;
-    subt_data->sub_num = sub_num;
-    subt_data->sub_errs = sub_errs;
-    subt_data->subtitles = return_sub;
-    return subt_data;
+    subt_data_array = malloc(sizeof(struct sub_data_array) +
result_count*sizeof(sub_data *));
+    subt_data_array->count = result_count;
+    for (i = 0; i < result_count; ++i) { /* if sub has not different
types of <P class>, result_count should be 1 */
+        subt_data_array->subdata[i] = malloc(sizeof(sub_data));
+        subt_data_array->subdata[i]->filename = (sub_format ==
SUB_SAMI)? strdup(results[i].sub_class): strdup(filename);
+        subt_data_array->subdata[i]->sub_uses_time = uses_time;
+        subt_data_array->subdata[i]->sub_num = results[i].sub_num;
+        subt_data_array->subdata[i]->sub_errs = results[i].sub_errs;
+        subt_data_array->subdata[i]->subtitles = results[i].subtitles;
+    }
+    free(results);
+    return subt_data_array;
 }

 #if 0
Index: subreader.h
===================================================================
--- subreader.h	(revision 29435)
+++ subreader.h	(working copy)
@@ -52,6 +52,11 @@
     unsigned char alignment;
 } subtitle;

+struct subtitle_sami {
+    subtitle parrent;
+    char sub_class[10];
+};
+
 typedef struct {
     subtitle *subtitles;
     char *filename;
@@ -60,11 +65,16 @@
     int sub_errs;
 } sub_data;

+struct sub_data_array {
+    int count;
+    sub_data *subdata[];
+};
+
 extern char *fribidi_charset;
 extern int flip_hebrew;
 extern int fribidi_flip_commas;

-sub_data* sub_read_file (char *filename, float pts);
+struct sub_data_array* sub_read_file (char *filename, float pts);
 subtitle* subcp_recode (subtitle *sub);
 // enca_fd is the file enca uses to determine the codepage.
 // setting to NULL disables enca.
Index: mencoder.c
===================================================================
--- mencoder.c	(revision 29435)
+++ mencoder.c	(working copy)
@@ -640,16 +640,24 @@
 // check .sub
 //  current_module="read_subtitles_file";
   if(sub_name && sub_name[0]){
-    subdata=sub_read_file(sub_name[0], sh_video->fps);
+    struct sub_data_array *subdata_array;
+    subdata_array=sub_read_file(sub_name[0], sh_video->fps);
+    subdata=subdata_array?subdata_array->subdata[0]:NULL;
+    for(i = 1; i < subdata_array->count; ++i)
sub_free(subdata_array->subdata[i]);
+    free(subdata_array);
     if(!subdata) mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadSub,sub_name[0]);
   } else
   if(sub_auto && filename) { // auto load sub file ...
     char **tmp = NULL;
     int i = 0;
     char *psub = get_path( "sub/" );
+    struct sub_data_array *subdata_array;
     tmp = sub_filenames((psub ? psub : ""), filename);
     free(psub);
-    subdata=sub_read_file(tmp[0], sh_video->fps);
+    subdata_array=sub_read_file(tmp[0], sh_video->fps);
+    subdata=subdata_array?subdata_array->subdata[0]:NULL;
+    for(i = 1; i < subdata_array->count; ++i)
sub_free(subdata_array->subdata[i]);
+    free(subdata_array);
     while (tmp[i])
       free(tmp[i++]);
     free(tmp);



More information about the MPlayer-dev-eng mailing list