Ticket #1401: ass_support_for_mencoder_with_embeddedfonts.patch

File ass_support_for_mencoder_with_embeddedfonts.patch, 14.4 KB (added by erappleman@…, 18 years ago)

ass support with embedded fonts

  • libmpcodecs/vf_fixpts.c

     
     1/*
     2    Copyright (C) 2007 Nicolas George <nicolas.george@normalesup.org>
     3
     4    This program is free software; you can redistribute it and/or modify
     5    it under the terms of the GNU General Public License as published by
     6    the Free Software Foundation; either version 2 of the License, or
     7    (at your option) any later version.
     8
     9    This program is distributed in the hope that it will be useful,
     10    but WITHOUT ANY WARRANTY; without even the implied warranty of
     11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12    GNU General Public License for more details.
     13
     14    You should have received a copy of the GNU General Public License
     15    along with this program; if not, write to the Free Software
     16    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
     17*/
     18
     19#include <stdio.h>
     20#include <stdlib.h>
     21#include <string.h>
     22#include <inttypes.h>
     23
     24#include "config.h"
     25#include "mp_msg.h"
     26#include "help_mp.h"
     27
     28#include "img_format.h"
     29#include "mp_image.h"
     30#include "vf.h"
     31
     32struct vf_priv_s {
     33    double current;
     34    double step;
     35    int autostart;
     36    int autostep;
     37    unsigned have_step: 1;
     38    unsigned print: 1;
     39};
     40
     41static int put_image(vf_instance_t *vf, mp_image_t *src, double pts)
     42{
     43    struct vf_priv_s *p = vf->priv;
     44
     45    if(p->print) {
     46        if(pts == MP_NOPTS_VALUE)
     47            printf("PTS: undef\n");
     48        else
     49            printf("PTS: %f\n", pts);
     50    }
     51    if(pts != MP_NOPTS_VALUE && p->autostart != 0) {
     52        p->current = pts;
     53        if(p->autostart > 0)
     54            p->autostart--;
     55    } else if(pts != MP_NOPTS_VALUE && p->autostep > 0) {
     56        p->step = pts - p->current;
     57        p->current = pts;
     58        p->autostep--;
     59        p->have_step = 1;
     60    } else if(p->have_step) {
     61        p->current += p->step;
     62        pts = p->current;
     63    } else {
     64        pts = MP_NOPTS_VALUE;
     65    }
     66    return vf_next_put_image(vf, src, pts);
     67}
     68
     69static void uninit(vf_instance_t *vf)
     70{
     71    free(vf->priv);
     72}
     73
     74static int parse_args(struct vf_priv_s *p, const char *args)
     75{
     76    int pos;
     77    double num, denom = 1;
     78    int iarg;
     79
     80    while(*args != 0) {
     81        pos = 0;
     82        if(sscanf(args, "print%n", &pos) == 0 && pos > 0) {
     83            p->print = 1;
     84        } else if(sscanf(args, "fps=%lf%n/%lf%n", &num, &pos, &denom, &pos) >= 1
     85            && pos > 0) {
     86            p->step = denom / num;
     87            p->have_step = 1;
     88        } else if(sscanf(args, "start=%lf%n", &num, &pos) >= 1 && pos > 0) {
     89            p->current = num;
     90        } else if(sscanf(args, "autostart=%d%n", &iarg, &pos) == 1 && pos > 0) {
     91            p->autostart = iarg;
     92        } else if(sscanf(args, "autofps=%d%n", &iarg, &pos) == 1 && pos > 0) {
     93            p->autostep = iarg;
     94        } else {
     95            mp_msg(MSGT_VFILTER, MSGL_FATAL,
     96                "fixpts: unknown suboption: %s\n", args);
     97            return 0;
     98        }
     99        args += pos;
     100        if(*args == ':')
     101            args++;
     102    }
     103    return 1;
     104}
     105
     106static int open(vf_instance_t *vf, char *args)
     107{
     108    struct vf_priv_s *p;
     109    struct vf_priv_s ptmp = {
     110        .current = 0,
     111        .step = 0,
     112        .autostart = 0,
     113        .autostep = 0,
     114        .have_step = 0,
     115        .print = 0,
     116    };
     117
     118    if(!parse_args(&ptmp, args == NULL ? "" : args))
     119        return 0;
     120
     121    vf->put_image = put_image;
     122    vf->uninit = uninit;
     123    vf->priv = p = malloc(sizeof(struct vf_priv_s));
     124    *p = ptmp;
     125    p->current = -p->step;
     126
     127    return 1;
     128}
     129
     130vf_info_t vf_info_fixpts = {
     131  "Fix presentation timestamps",
     132  "fixpts",
     133  "Nicolas George",
     134  "",
     135  &open,
     136  NULL
     137};
  • libmpcodecs/vf.c

     
    9999extern const vf_info_t vf_info_blackframe;
    100100extern const vf_info_t vf_info_geq;
    101101extern const vf_info_t vf_info_ow;
     102extern const vf_info_t vf_info_fixpts;
    102103
    103104// list of available filters:
    104105static const vf_info_t* const filter_list[]={
     
    191192    &vf_info_yadif,
    192193    &vf_info_blackframe,
    193194    &vf_info_ow,
     195    &vf_info_fixpts,
    194196    NULL
    195197};
    196198
  • Makefile

     
    125125              libmpcodecs/vf_field.c \
    126126              libmpcodecs/vf_fil.c \
    127127              libmpcodecs/vf_filmdint.c \
     128              libmpcodecs/vf_fixpts.c \
    128129              libmpcodecs/vf_flip.c \
    129130              libmpcodecs/vf_format.c \
    130131              libmpcodecs/vf_framestep.c \
  • cfg-mencoder.h

     
    213213       
    214214        {"odml", &write_odml, CONF_TYPE_FLAG, CONF_GLOBAL, 0, 1, NULL},
    215215        {"noodml", &write_odml, CONF_TYPE_FLAG, CONF_GLOBAL, 1, 0, NULL},
     216
     217        {"keep-pts", &keep_pts, CONF_TYPE_FLAG, 0, 0, 1, NULL},
     218        {"nokeep-pts", &keep_pts, CONF_TYPE_FLAG, 0, 1, 0, NULL},
    216219       
    217220        // info header strings
    218221        {"info", info_conf, CONF_TYPE_SUBCONFIG, CONF_GLOBAL, 0, 0, NULL},
  • DOCS/man/en/mplayer.1

     
    71907190Threshold below which a pixel value is considered black (default: 32).
    71917191.RE
    71927192.
     7193.TP
     7194.B fixpts[=options]
     7195Fixes the presentation timestamps (PTS) of the frames.
     7196By default, the PTS passed to the next filter is dropped, but the following
     7197options can change that:
     7198.RSs
     7199.IPs print
     7200Print the incoming PTS.
     7201.IPs fps=<fps>
     7202Specify a frame per second value.
     7203.IPs start=<pts>
     7204Specify an initial value for the PTS.
     7205.IPs autostart=<n>
     7206Uses the
     7207.IR n th
     7208incoming PTS as the initial PTS.
     7209All previous pts are kept, so setting a huge value or \-1 keeps the PTS
     7210intact.
     7211.IPs autofps=<n>
     7212Uses the
     7213.IR n th
     7214incoming PTS after the end of autostart to determine the framerate.
     7215.RE
     7216.sp 1
     7217.RS
     7218.I EXAMPLE:
     7219.RE
     7220.PD 0
     7221.RSs
     7222.IPs "\-vf fixpts=fps=24000/1001,ass,fixpts"
     7223Generates a new sequence of PTS, uses it for ASS subtitles, then drops it.
     7224Generating a new sequence is useful when the timestamps are reset during the
     7225program; this is frequent on DVDs.
     7226Dropping it may be necessary to avoid confusing encoders.
     7227.RE
     7228.PD 1
     7229.sp 1
     7230.RS
     7231.I NOTE:
     7232Using this filter together with any sort of seeking (including -ss and EDLs)
     7233may make demons fly out of your nose.
     7234.RE
    71937235.
    71947236.
    71957237.SH "GENERAL ENCODING OPTIONS (MENCODER ONLY)"
     
    73127354Do not write OpenDML index for AVI files >1GB.
    73137355.
    73147356.TP
     7357.B \-keep\-pts
     7358Send the original presentation timestamp (PTS) down the filter and encoder
     7359chain.
     7360This may cause incorrect output ("badly interleaved") if the original PTS
     7361are wrong or the framerate is changed, but can be necessary for certain
     7362filters (such as ASS).
     7363.
     7364.TP
    73157365.B \-noskip
    73167366Do not skip frames.
    73177367.
  • libass/ass_cache.c

     
    291291        free(value);
    292292}
    293293
     294static int glyph_compare(void* key1, void* key2, size_t key_size) {
     295        glyph_hash_key_t* a = key1;
     296        glyph_hash_key_t* b = key2;
     297        return
     298                a->font == b->font &&
     299                a->size == b->size &&
     300                a->ch == b->ch &&
     301                a->bold == b->bold &&
     302                a->italic == b->italic &&
     303                a->scale_x == b->scale_x &&
     304                a->scale_y == b->scale_y &&
     305                a->advance.x == b->advance.x &&
     306                a->advance.y == b->advance.y &&
     307                a->outline == b->outline;
     308}
     309
     310static unsigned glyph_hash(void* buf, size_t len)
     311{
     312        glyph_hash_key_t* g = buf;
     313        unsigned hval = FNV1_32A_INIT;
     314        hval = fnv_32a_buf(&g->font, sizeof(g->font), hval);
     315        hval = fnv_32a_buf(&g->size, sizeof(g->size), hval);
     316        hval = fnv_32a_buf(&g->ch, sizeof(g->ch), hval);
     317        hval = fnv_32a_buf(&g->bold, sizeof(g->bold), hval);
     318        hval = fnv_32a_buf(&g->italic, sizeof(g->italic), hval);
     319        hval = fnv_32a_buf(&g->scale_x, sizeof(g->scale_x), hval);
     320        hval = fnv_32a_buf(&g->scale_y, sizeof(g->scale_y), hval);
     321        hval = fnv_32a_buf(&g->advance.x, sizeof(g->advance.x), hval);
     322        hval = fnv_32a_buf(&g->advance.y, sizeof(g->advance.y), hval);
     323        hval = fnv_32a_buf(&g->outline, sizeof(g->outline), hval);
     324        return hval;
     325}
     326
    294327void* cache_add_glyph(glyph_hash_key_t* key, glyph_hash_val_t* val)
    295328{
    296329        return hashmap_insert(glyph_cache, key, val);
     
    311344        glyph_cache = hashmap_init(sizeof(glyph_hash_key_t),
    312345                                   sizeof(glyph_hash_val_t),
    313346                                   0xFFFF + 13,
    314                                    glyph_hash_dtor, NULL, NULL);
     347                                   glyph_hash_dtor,
     348                                   glyph_compare,
     349                                   glyph_hash);
    315350}
    316351
    317352void ass_glyph_cache_done(void)
  • mencoder.c

     
    198198
    199199int auto_expand=1;
    200200int encode_duplicates=1;
     201int keep_pts=0;
    201202
    202203// infos are empty by default
    203204char *info_name=NULL;
     
    361362
    362363static muxer_t* muxer=NULL;
    363364
     365void add_subtitles(char *filename, float fps, int silent)
     366{
     367    sub_data *subd;
     368#ifdef CONFIG_ASS
     369    ass_track_t *asst = 0;
     370#endif
     371
     372    if (filename == NULL) return;
     373
     374    subd = sub_read_file(filename, fps);
     375#ifdef CONFIG_ASS
     376    if (ass_enabled)
     377#ifdef CONFIG_ICONV
     378        asst = ass_read_file(ass_library, filename, sub_cp);
     379#else
     380        asst = ass_read_file(ass_library, filename, 0);
     381#endif
     382    if (ass_enabled && subd && !asst)
     383        asst = ass_read_subdata(ass_library, subd, fps);
     384
     385    if (!asst && !subd && !silent)
     386#else
     387    if(!subd && !silent)
     388#endif
     389        mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_CantLoadSub,
     390                filename_recode(filename));
     391 
     392#ifdef CONFIG_ASS
     393    if (!asst && !subd) return;
     394    ass_track = asst;
     395#else
     396    if (!subd) return;
     397#endif
     398    mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FILE_SUB_FILENAME=%s\n",
     399           filename_recode(filename));
     400    subdata = subd;
     401}
     402
    364403void print_wave_header(WAVEFORMATEX *h, int verbose_level);
    365404
    366405int main(int argc,char* argv[]){
     
    562601  m_entry_set_options(mconfig,&filelist[curfile]);
    563602  filename = filelist[curfile].name;
    564603 
     604#ifdef CONFIG_ASS
     605  ass_library = ass_init();
     606#endif
     607
    565608  if(!filename){
    566609        mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_MissingFilename);
    567610        mencoder_exit(1,NULL);
     
    685728    }
    686729  }
    687730
    688 // after reading video params we should load subtitles because
    689 // we know fps so now we can adjust subtitles time to ~6 seconds AST
    690 // check .sub
    691 //  current_module="read_subtitles_file";
    692   if(sub_name && sub_name[0]){
    693     subdata=sub_read_file(sub_name[0], sh_video->fps);
    694     if(!subdata) mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadSub,sub_name[0]);
    695   } else
    696   if(sub_auto && filename) { // auto load sub file ...
    697     char **tmp = NULL;
    698     int i = 0;
    699     char *psub = get_path( "sub/" );
    700     tmp = sub_filenames((psub ? psub : ""), filename);
    701     free(psub);
    702     subdata=sub_read_file(tmp[0], sh_video->fps);
    703     while (tmp[i])
    704       free(tmp[i++]);
    705     free(tmp);
    706   }
    707 
    708731// set up video encoder:
    709732
    710733if (!curfile) { // curfile is non zero when a second file is opened
     
    882905    ve = sh_video->vfilter;
    883906  } else sh_video->vfilter = ve;
    884907    // append 'expand' filter, it fixes stride problems and renders osd:
     908#ifdef CONFIG_ASS
     909    if (auto_expand && !ass_enabled) { /* we do not want both */
     910#else
    885911    if (auto_expand) {
     912#endif
    886913      char* vf_args[] = { "osd", "1", NULL };
    887914      sh_video->vfilter=vf_open_filter(sh_video->vfilter,"expand",vf_args);
    888915    }
     916
     917#ifdef CONFIG_ASS
     918  if(ass_enabled) {
     919    int i;
     920    int insert = 1;
     921    if (vf_settings)
     922      for (i = 0; vf_settings[i].name; ++i)
     923        if (strcmp(vf_settings[i].name, "ass") == 0) {
     924          insert = 0;
     925          break;
     926        }
     927    if (insert) {
     928      extern vf_info_t vf_info_ass;
     929      vf_info_t* libass_vfs[] = {&vf_info_ass, NULL};
     930      char* vf_arg[] = {"auto", "1", NULL};
     931      vf_instance_t* vf_ass = vf_open_plugin(libass_vfs,sh_video->vfilter,"ass",vf_arg);
     932      if (vf_ass)
     933        sh_video->vfilter=(void*)vf_ass;
     934      else
     935        mp_msg(MSGT_CPLAYER,MSGL_ERR, "ASS: cannot add video filter\n");
     936    }
     937    if (!keep_pts) {
     938      keep_pts = 1;
     939      mp_msg(MSGT_MENCODER, MSGL_WARN, "Warning: -ass implies -keep-pts, "
     940        "which may cause \"badly interleaved\" files.\n");
     941    }
     942
     943    if (ass_library) {
     944      for (i = 0; i < demuxer->num_attachments; ++i) {
     945        demux_attachment_t* att = demuxer->attachments + i;
     946        if (extract_embedded_fonts &&
     947            att->name && att->type && att->data && att->data_size &&
     948            (strcmp(att->type, "application/x-truetype-font") == 0 ||
     949             strcmp(att->type, "application/x-font") == 0))
     950          ass_add_font(ass_library, att->name, att->data, att->data_size);
     951      }
     952    }
     953  }
     954#endif
     955
    889956    sh_video->vfilter=append_filters(sh_video->vfilter);
    890957
     958#ifdef CONFIG_ASS
     959  if (ass_enabled)
     960    ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter, VFCTRL_INIT_EOSD, ass_library);
     961#endif
     962
     963// after reading video params we should load subtitles because
     964// we know fps so now we can adjust subtitles time to ~6 seconds AST
     965// check .sub
     966//  current_module="read_subtitles_file";
     967  if(sub_name && sub_name[0]){
     968    for (i = 0; sub_name[i] != NULL; ++i)
     969        add_subtitles (sub_name[i], sh_video->fps, 0);
     970  } else
     971  if(sub_auto && filename) { // auto load sub file ...
     972    char **tmp = NULL;
     973    int i = 0;
     974    char *psub = get_path( "sub/" );
     975    tmp = sub_filenames((psub ? psub : ""), filename);
     976    free(psub);
     977    while (tmp[i])
     978    {
     979      add_subtitles (tmp[i], sh_video->fps, 0);
     980      free(tmp[i++]);
     981    }
     982    free(tmp);
     983  }
     984
    891985    mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n");
    892986    init_best_video_codec(sh_video,video_codec_list,video_fm_list);
    893987    mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n");
     
    13431437    // decode_video will callback down to ve_*.c encoders, through the video filters
    13441438    {void *decoded_frame = decode_video(sh_video,frame_data.start,frame_data.in_size,
    13451439      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);
    1346     blit_frame = decoded_frame && filter_video(sh_video, decoded_frame, MP_NOPTS_VALUE);}
     1440    blit_frame = decoded_frame && filter_video(sh_video, decoded_frame,
     1441        keep_pts ? sh_video->pts : MP_NOPTS_VALUE);}
    13471442   
    13481443    if (sh_video->vf_initialized < 0) mencoder_exit(1, NULL);
    13491444