[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