[cosmetics] update date in GPL header
[vuplus_xbmc] / xbmc / cores / dvdplayer / DVDSubtitles / DVDSubtitlesLibass.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://www.xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "DVDSubtitlesLibass.h"
22 #include "DVDClock.h"
23 #include "filesystem/SpecialProtocol.h"
24 #include "settings/GUISettings.h"
25 #include "utils/log.h"
26 #include "threads/SingleLock.h"
27 #include "threads/Atomics.h"
28
29 using namespace std;
30
31 static void libass_log(int level, const char *fmt, va_list args, void *data)
32 {
33   if(level >= 5)
34     return;
35   CStdString log;
36   log.FormatV(fmt, args);
37   CLog::Log(LOGDEBUG, "CDVDSubtitlesLibass: [ass] %s", log.c_str());
38 }
39
40 CDVDSubtitlesLibass::CDVDSubtitlesLibass()
41 {
42
43   m_track = NULL;
44   m_library = NULL;
45   m_renderer = NULL;
46   m_references = 1;
47
48   if(!m_dll.Load())
49   {
50     CLog::Log(LOGERROR, "CDVDSubtitlesLibass: Failed to load libass library");
51     return;
52   }
53
54   //Setting the font directory to the temp dir(where mkv fonts are extracted to)
55   CStdString strPath = "special://temp/fonts/";
56
57   CLog::Log(LOGINFO, "CDVDSubtitlesLibass: Creating ASS library structure");
58   m_library  = m_dll.ass_library_init();
59   if(!m_library)
60     return;
61
62   m_dll.ass_set_message_cb(m_library, libass_log, this);
63
64   CLog::Log(LOGINFO, "CDVDSubtitlesLibass: Initializing ASS library font settings");
65   // libass uses fontconfig (system lib) which is not wrapped
66   //  so translate the path before calling into libass
67   m_dll.ass_set_fonts_dir(m_library,  CSpecialProtocol::TranslatePath(strPath).c_str());
68   m_dll.ass_set_extract_fonts(m_library, 1);
69   m_dll.ass_set_style_overrides(m_library, NULL);
70
71   CLog::Log(LOGINFO, "CDVDSubtitlesLibass: Initializing ASS Renderer");
72
73   m_renderer = m_dll.ass_renderer_init(m_library);
74
75   if(!m_renderer)
76     return;
77
78   //Setting default font to the Arial in \media\fonts (used if FontConfig fails)
79   strPath = "special://xbmc/media/Fonts/";
80   strPath += g_guiSettings.GetString("subtitles.font");
81   int fc = !g_guiSettings.GetBool("subtitles.overrideassfonts");
82
83   m_dll.ass_set_margins(m_renderer, 0, 0, 0, 0);
84   m_dll.ass_set_use_margins(m_renderer, 0);
85   m_dll.ass_set_font_scale(m_renderer, 1);
86
87   // libass uses fontconfig (system lib) which is not wrapped
88   //  so translate the path before calling into libass
89   m_dll.ass_set_fonts(m_renderer, CSpecialProtocol::TranslatePath(strPath).c_str(), "Arial", fc, NULL, 1);
90 }
91
92
93 CDVDSubtitlesLibass::~CDVDSubtitlesLibass()
94 {
95   if(m_dll.IsLoaded())
96   {
97     if(m_track)
98       m_dll.ass_free_track(m_track);
99     m_dll.ass_renderer_done(m_renderer);
100     m_dll.ass_library_done(m_library);
101     m_dll.Unload();
102   }
103 }
104
105 /*Decode Header of SSA, needed to properly decode demux packets*/
106 bool CDVDSubtitlesLibass::DecodeHeader(char* data, int size)
107 {
108   CSingleLock lock(m_section);
109   if(!m_library || !data)
110     return false;
111
112   if(!m_track)
113   {
114     CLog::Log(LOGINFO, "CDVDSubtitlesLibass: Creating new ASS track");
115     m_track = m_dll.ass_new_track(m_library) ;
116   }
117
118   m_dll.ass_process_codec_private(m_track, data, size);
119   return true;
120 }
121
122 bool CDVDSubtitlesLibass::DecodeDemuxPkt(char* data, int size, double start, double duration)
123 {
124   CSingleLock lock(m_section);
125   if(!m_track)
126   {
127     CLog::Log(LOGERROR, "CDVDSubtitlesLibass: No SSA header found.");
128     return false;
129   }
130
131   m_dll.ass_process_chunk(m_track, data, size, DVD_TIME_TO_MSEC(start), DVD_TIME_TO_MSEC(duration));
132   return true;
133 }
134
135 bool CDVDSubtitlesLibass::CreateTrack(char* buf)
136 {
137   CSingleLock lock(m_section);
138   if(!m_library)
139   {
140     CLog::Log(LOGERROR, "CDVDSubtitlesLibass: %s - No ASS library struct", __FUNCTION__);
141     return false;
142   }
143
144   CLog::Log(LOGINFO, "SSA Parser: Creating m_track from SSA buffer");
145
146   m_track = m_dll.ass_read_memory(m_library, buf, 0, 0);
147   if(m_track == NULL)
148     return false;
149
150   return true;
151 }
152
153 ASS_Image* CDVDSubtitlesLibass::RenderImage(int imageWidth, int imageHeight, double pts, int *changes)
154 {
155   CSingleLock lock(m_section);
156   if(!m_renderer || !m_track)
157   {
158     CLog::Log(LOGERROR, "CDVDSubtitlesLibass: %s - Missing ASS structs(m_track or m_renderer)", __FUNCTION__);
159     return NULL;
160   }
161
162   m_dll.ass_set_frame_size(m_renderer, imageWidth, imageHeight);
163   return m_dll.ass_render_frame(m_renderer, m_track, DVD_TIME_TO_MSEC(pts), changes);
164 }
165
166 ASS_Event* CDVDSubtitlesLibass::GetEvents()
167 {
168   CSingleLock lock(m_section);
169   if(!m_track)
170   {
171     CLog::Log(LOGERROR, "CDVDSubtitlesLibass: %s -  Missing ASS structs(m_track)", __FUNCTION__);
172     return NULL;
173   }
174   return m_track->events;
175 }
176
177 int CDVDSubtitlesLibass::GetNrOfEvents()
178 {
179   CSingleLock lock(m_section);
180   if(!m_track)
181     return 0;
182   return m_track->n_events;
183 }
184