[MPlayer-dev-eng] MEncoder: libass support (patch)

Joel Yliluoma bisqwit at iki.fi
Tue Sep 18 23:44:05 CEST 2007


The patch attached below adds support for libass subtitle rendering
in MEncoder. It is based on the code from MPlayer.

Example commandline to test:
   mencoder test0.avi -oac copy -ovc x264 -x264encopts crf=20 \
     -o test2.avi -ass -sub test0.sub -endpos 3 \
     -ass-font-scale 1.5 \
     -ass-force-style FontName='URW Bookman L',Default.Bold=1 
Example subtitle file to test:
{20}{360}{\c&HA0A0A0}abc|{\c&HA0FFA0}def|{\c&HA0FFA0}ghi

Summary of changes in the patch:

+ Added add_subtitles() from MPlayer
+ Removed MPlayer-specific code (mpctx references)
+ Added ass_library initialization
+ Moved the subtitle loading after the initialization
   of ass_library
+ Disabled the "expand" filter if -ass option is used;
   the expand filter conflicts with libass OSD.
+ Added automatic -vf ass when -ass is used. However, it
   seems that it is still explicitly needed as well.
+ Changed the subtitle loading code so that it uses the
   add_subtitles() function (which was copied from MPlayer)
   instead of calling sub_read_file() directly.
+ Passes sh_video->pts as the "pts" value to filter_video
   instead of passing MP_NOPTS_VALUE. This fixes the problem
   that prevents subtitles from being seen at all.

The patch:

Index: mencoder.c
===================================================================
--- mencoder.c	(revision 24130)
+++ mencoder.c	(working copy)
@@ -368,6 +368,49 @@

  extern void print_wave_header(WAVEFORMATEX *h, int verbose_level);

+void add_subtitles(char *filename, float fps, int silent)
+{
+    sub_data *subd;
+#ifdef USE_ASS
+    ass_track_t *asst = 0;
+#endif
+
+    if (filename == NULL) return;
+
+    subd = sub_read_file(filename, fps);
+#ifdef USE_ASS
+    if (ass_enabled)
+#ifdef USE_ICONV
+        asst = ass_read_file(ass_library, filename, sub_cp);
+#else
+        asst = ass_read_file(ass_library, filename, 0);
+#endif
+    if (ass_enabled && subd && !asst)
+        asst = ass_read_subdata(ass_library, subd, fps);
+
+    if (!asst && !subd && !silent)
+#else
+    if(!subd && !silent) 
+#endif
+        mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_CantLoadSub,
+		filename_recode(filename));
+ 
+#ifdef USE_ASS
+    if (!asst && !subd) return;
+    ass_track = asst;
+#else
+    if (!subd) return;
+#endif
+    //mpctx->set_of_subtitles[mpctx->set_of_sub_size] = subd;
+    //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));
+    //++mpctx->set_of_sub_size;
+    //mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_AddedSubtitleFile, mpctx->set_of_sub_size,
+	//    filename_recode(filename));
+    subdata = subd;
+}
+
  int main(int argc,char* argv[]){

  stream_t* stream=NULL;
@@ -564,6 +607,10 @@
    m_entry_set_options(mconfig,&filelist[curfile]);
    filename = filelist[curfile].name;

+#ifdef USE_ASS
+  ass_library = ass_init();
+#endif
+
    if(!filename){
  	mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_MissingFilename);
  	mencoder_exit(1,NULL);
@@ -664,26 +711,6 @@
      }
    }

-// after reading video params we should load subtitles because
-// we know fps so now we can adjust subtitles time to ~6 seconds AST
-// check .sub
-//  current_module="read_subtitles_file";
-  if(sub_name && sub_name[0]){
-    subdata=sub_read_file(sub_name[0], sh_video->fps);
-    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/" );
-    tmp = sub_filenames((psub ? psub : ""), filename);
-    free(psub);
-    subdata=sub_read_file(tmp[0], sh_video->fps);
-    while (tmp[i])
-      free(tmp[i++]);
-    free(tmp);
-  }
-
  // set up video encoder:

  if (!curfile) { // curfile is non zero when a second file is opened
@@ -864,12 +891,68 @@
      ve = sh_video->vfilter;
    } else sh_video->vfilter = ve;
      // append 'expand' filter, it fixes stride problems and renders osd:
-    if (auto_expand) {
+ 
+    if (auto_expand && !ass_enabled) { /* conflicts with libass */
        char* vf_args[] = { "osd", "1", NULL };
        sh_video->vfilter=vf_open_filter(sh_video->vfilter,"expand",vf_args);
      }
+
+#ifdef USE_ASS
+  if(ass_enabled) {
+    int i;
+    int insert = 1;
+    if (vf_settings)
+      for (i = 0; vf_settings[i].name; ++i)
+        if (strcmp(vf_settings[i].name, "ass") == 0) {
+          insert = 0;
+          break;
+        }
+    if (insert) {
+      extern vf_info_t vf_info_ass;
+      vf_info_t* libass_vfs[] = {&vf_info_ass, NULL};
+      char* vf_arg[] = {"auto", "1", NULL};
+      vf_instance_t* vf_ass = vf_open_plugin(libass_vfs,sh_video->vfilter,"ass",vf_arg);
+      if (vf_ass)
+        sh_video->vfilter=(void*)vf_ass;
+      else
+        mp_msg(MSGT_CPLAYER,MSGL_ERR, "ASS: cannot add video filter\n");
+    }
+  }
+#endif
+
      sh_video->vfilter=append_filters(sh_video->vfilter);

+
+#ifdef USE_ASS
+  if (ass_enabled)
+    ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter, VFCTRL_INIT_EOSD, ass_library);
+#endif
+
+// after reading video params we should load subtitles because
+// we know fps so now we can adjust subtitles time to ~6 seconds AST
+// check .sub
+//  current_module="read_subtitles_file";
+  if(sub_name && sub_name[0]){
+    for (i = 0; sub_name[i] != NULL; ++i) 
+        add_subtitles (sub_name[i], sh_video->fps, 0); 
+    ///subdata=sub_read_file(sub_name[0], sh_video->fps);
+    ///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/" );
+    tmp = sub_filenames((psub ? psub : ""), filename);
+    free(psub);
+    while (tmp[i])
+    {
+      add_subtitles (tmp[i], sh_video->fps, 0);
+      free(tmp[i++]);
+    }
+    free(tmp);
+  }
+
+
      mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n");
      init_best_video_codec(sh_video,video_codec_list,video_fm_list);
      mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n");
@@ -1324,7 +1407,7 @@
      // decode_video will callback down to ve_*.c encoders, through the video filters
      {void *decoded_frame = decode_video(sh_video,frame_data.start,frame_data.in_size,
        skip_flag>0 && (!sh_video->vfilter || ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter, VFCTRL_SKIP_NEXT_FRAME, 0) != CONTROL_TRUE), MP_NOPTS_VALUE);
-    blit_frame = decoded_frame && filter_video(sh_video, decoded_frame, MP_NOPTS_VALUE);}
+    blit_frame = decoded_frame && filter_video(sh_video, decoded_frame, sh_video->pts/*MP_NOPTS_VALUE*/);}

      if (sh_video->vf_inited < 0) mencoder_exit(1, NULL);


-- 
Joel Yliluoma
http://iki.fi/bisqwit/



More information about the MPlayer-dev-eng mailing list