/src/ffmpeg/libavcodec/ass.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /*  | 
2  |  |  * SSA/ASS common functions  | 
3  |  |  * Copyright (c) 2010  Aurelien Jacobs <aurel@gnuage.org>  | 
4  |  |  *  | 
5  |  |  * This file is part of FFmpeg.  | 
6  |  |  *  | 
7  |  |  * FFmpeg is free software; you can redistribute it and/or  | 
8  |  |  * modify it under the terms of the GNU Lesser General Public  | 
9  |  |  * License as published by the Free Software Foundation; either  | 
10  |  |  * version 2.1 of the License, or (at your option) any later version.  | 
11  |  |  *  | 
12  |  |  * FFmpeg is distributed in the hope that it will be useful,  | 
13  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of  | 
14  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  | 
15  |  |  * Lesser General Public License for more details.  | 
16  |  |  *  | 
17  |  |  * You should have received a copy of the GNU Lesser General Public  | 
18  |  |  * License along with FFmpeg; if not, write to the Free Software  | 
19  |  |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA  | 
20  |  |  */  | 
21  |  |  | 
22  |  | #include "avcodec.h"  | 
23  |  | #include "ass.h"  | 
24  |  | #include "libavutil/avstring.h"  | 
25  |  | #include "libavutil/bprint.h"  | 
26  |  | #include "libavutil/mem.h"  | 
27  |  | #include "version.h"  | 
28  |  |  | 
29  |  | int ff_ass_subtitle_header_full(AVCodecContext *avctx,  | 
30  |  |                                 int play_res_x, int play_res_y,  | 
31  |  |                                 const char *font, int font_size,  | 
32  |  |                                 int primary_color, int secondary_color,  | 
33  |  |                                 int outline_color, int back_color,  | 
34  |  |                                 int bold, int italic, int underline,  | 
35  |  |                                 int border_style, int alignment)  | 
36  | 14.0k  | { | 
37  | 14.0k  |     avctx->subtitle_header = av_asprintf(  | 
38  | 14.0k  |              "[Script Info]\n"  | 
39  | 14.0k  |              "; Script generated by FFmpeg/Lavc%s\n"  | 
40  | 14.0k  |              "ScriptType: v4.00+\n"  | 
41  | 14.0k  |              "PlayResX: %d\n"  | 
42  | 14.0k  |              "PlayResY: %d\n"  | 
43  | 14.0k  |              "ScaledBorderAndShadow: yes\n"  | 
44  | 14.0k  |              "YCbCr Matrix: None\n"  | 
45  | 14.0k  |              "\n"  | 
46  | 14.0k  |              "[V4+ Styles]\n"  | 
47  |  |  | 
48  |  |              /* ASS (v4+) header */  | 
49  | 14.0k  |              "Format: Name, "  | 
50  | 14.0k  |              "Fontname, Fontsize, "  | 
51  | 14.0k  |              "PrimaryColour, SecondaryColour, OutlineColour, BackColour, "  | 
52  | 14.0k  |              "Bold, Italic, Underline, StrikeOut, "  | 
53  | 14.0k  |              "ScaleX, ScaleY, "  | 
54  | 14.0k  |              "Spacing, Angle, "  | 
55  | 14.0k  |              "BorderStyle, Outline, Shadow, "  | 
56  | 14.0k  |              "Alignment, MarginL, MarginR, MarginV, "  | 
57  | 14.0k  |              "Encoding\n"  | 
58  |  |  | 
59  | 14.0k  |              "Style: "  | 
60  | 14.0k  |              "Default,"             /* Name */  | 
61  | 14.0k  |              "%s,%d,"               /* Font{name,size} */ | 
62  | 14.0k  |              "&H%x,&H%x,&H%x,&H%x," /* {Primary,Secondary,Outline,Back}Colour */ | 
63  | 14.0k  |              "%d,%d,%d,0,"          /* Bold, Italic, Underline, StrikeOut */  | 
64  | 14.0k  |              "100,100,"             /* Scale{X,Y} */ | 
65  | 14.0k  |              "0,0,"                 /* Spacing, Angle */  | 
66  | 14.0k  |              "%d,1,0,"              /* BorderStyle, Outline, Shadow */  | 
67  | 14.0k  |              "%d,10,10,10,"         /* Alignment, Margin[LRV] */  | 
68  | 14.0k  |              "1\n"                  /* Encoding */  | 
69  |  |  | 
70  | 14.0k  |              "\n"  | 
71  | 14.0k  |              "[Events]\n"  | 
72  | 14.0k  |              "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n",  | 
73  | 14.0k  |              !(avctx->flags & AV_CODEC_FLAG_BITEXACT) ? AV_STRINGIFY(LIBAVCODEC_VERSION) : "",  | 
74  | 14.0k  |              play_res_x, play_res_y, font, font_size,  | 
75  | 14.0k  |              primary_color, secondary_color, outline_color, back_color,  | 
76  | 14.0k  |              -bold, -italic, -underline, border_style, alignment);  | 
77  |  |  | 
78  | 14.0k  |     if (!avctx->subtitle_header)  | 
79  | 0  |         return AVERROR(ENOMEM);  | 
80  | 14.0k  |     avctx->subtitle_header_size = strlen(avctx->subtitle_header);  | 
81  | 14.0k  |     return 0;  | 
82  | 14.0k  | }  | 
83  |  |  | 
84  |  | int ff_ass_subtitle_header(AVCodecContext *avctx,  | 
85  |  |                            const char *font, int font_size,  | 
86  |  |                            int color, int back_color,  | 
87  |  |                            int bold, int italic, int underline,  | 
88  |  |                            int border_style, int alignment)  | 
89  | 14.0k  | { | 
90  | 14.0k  |     return ff_ass_subtitle_header_full(avctx,  | 
91  | 14.0k  |                                ASS_DEFAULT_PLAYRESX, ASS_DEFAULT_PLAYRESY,  | 
92  | 14.0k  |                                font, font_size, color, color,  | 
93  | 14.0k  |                                back_color, back_color,  | 
94  | 14.0k  |                                bold, italic, underline,  | 
95  | 14.0k  |                                border_style, alignment);  | 
96  | 14.0k  | }  | 
97  |  |  | 
98  |  | int ff_ass_subtitle_header_default(AVCodecContext *avctx)  | 
99  | 10.9k  | { | 
100  | 10.9k  |     return ff_ass_subtitle_header(avctx, ASS_DEFAULT_FONT,  | 
101  | 10.9k  |                                ASS_DEFAULT_FONT_SIZE,  | 
102  | 10.9k  |                                ASS_DEFAULT_COLOR,  | 
103  | 10.9k  |                                ASS_DEFAULT_BACK_COLOR,  | 
104  | 10.9k  |                                ASS_DEFAULT_BOLD,  | 
105  | 10.9k  |                                ASS_DEFAULT_ITALIC,  | 
106  | 10.9k  |                                ASS_DEFAULT_UNDERLINE,  | 
107  | 10.9k  |                                ASS_DEFAULT_BORDERSTYLE,  | 
108  | 10.9k  |                                ASS_DEFAULT_ALIGNMENT);  | 
109  | 10.9k  | }  | 
110  |  |  | 
111  |  | char *ff_ass_get_dialog(int readorder, int layer, const char *style,  | 
112  |  |                         const char *speaker, const char *text)  | 
113  | 4.42M  | { | 
114  | 4.42M  |     return av_asprintf("%d,%d,%s,%s,0,0,0,,%s", | 
115  | 4.42M  |                        readorder, layer, style ? style : "Default",  | 
116  | 4.42M  |                        speaker ? speaker : "", text);  | 
117  | 4.42M  | }  | 
118  |  |  | 
119  |  | int ff_ass_add_rect2(AVSubtitle *sub, const char *dialog,  | 
120  |  |                     int readorder, int layer, const char *style,  | 
121  |  |                     const char *speaker, unsigned *nb_rect_allocated)  | 
122  | 4.42M  | { | 
123  | 4.42M  |     AVSubtitleRect **rects = sub->rects, *rect;  | 
124  | 4.42M  |     char *ass_str;  | 
125  | 4.42M  |     uint64_t new_nb = 0;  | 
126  |  |  | 
127  | 4.42M  |     if (sub->num_rects >= UINT_MAX)  | 
128  | 0  |         return AVERROR(ENOMEM);  | 
129  |  |  | 
130  | 4.42M  |     if (nb_rect_allocated && *nb_rect_allocated <= sub->num_rects) { | 
131  | 14.1k  |         if (sub->num_rects < UINT_MAX / 17 * 16) { | 
132  | 14.1k  |             new_nb = sub->num_rects + sub->num_rects/16 + 1;  | 
133  | 14.1k  |         } else  | 
134  | 0  |             new_nb = UINT_MAX;  | 
135  | 4.41M  |     } else if (!nb_rect_allocated)  | 
136  | 1.42M  |         new_nb = sub->num_rects + 1;  | 
137  |  |  | 
138  | 4.42M  |     if (new_nb) { | 
139  | 1.43M  |         rects = av_realloc_array(rects, new_nb, sizeof(*sub->rects));  | 
140  | 1.43M  |         if (!rects)  | 
141  | 0  |             return AVERROR(ENOMEM);  | 
142  | 1.43M  |         if (nb_rect_allocated)  | 
143  | 14.1k  |             *nb_rect_allocated = new_nb;  | 
144  | 1.43M  |         sub->rects = rects;  | 
145  | 1.43M  |     }  | 
146  |  |  | 
147  | 4.42M  |     rect       = av_mallocz(sizeof(*rect));  | 
148  | 4.42M  |     if (!rect)  | 
149  | 0  |         return AVERROR(ENOMEM);  | 
150  | 4.42M  |     rects[sub->num_rects++] = rect;  | 
151  | 4.42M  |     rect->type = SUBTITLE_ASS;  | 
152  | 4.42M  |     ass_str = ff_ass_get_dialog(readorder, layer, style, speaker, dialog);  | 
153  | 4.42M  |     if (!ass_str)  | 
154  | 0  |         return AVERROR(ENOMEM);  | 
155  | 4.42M  |     rect->ass = ass_str;  | 
156  | 4.42M  |     return 0;  | 
157  | 4.42M  | }  | 
158  |  |  | 
159  |  | int ff_ass_add_rect(AVSubtitle *sub, const char *dialog,  | 
160  |  |                     int readorder, int layer, const char *style,  | 
161  |  |                     const char *speaker)  | 
162  | 1.42M  | { | 
163  | 1.42M  |     return ff_ass_add_rect2(sub, dialog, readorder, layer, style, speaker, NULL);  | 
164  | 1.42M  | }  | 
165  |  |  | 
166  |  | void ff_ass_decoder_flush(AVCodecContext *avctx)  | 
167  | 141k  | { | 
168  | 141k  |     FFASSDecoderContext *s = avctx->priv_data;  | 
169  | 141k  |     if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP))  | 
170  | 141k  |         s->readorder = 0;  | 
171  | 141k  | }  | 
172  |  |  | 
173  |  | void ff_ass_bprint_text_event(AVBPrint *buf, const char *p, int size,  | 
174  |  |                              const char *linebreaks, int keep_ass_markup)  | 
175  | 616k  | { | 
176  | 616k  |     const char *p_end = p + size;  | 
177  |  |  | 
178  | 63.2M  |     for (; p < p_end && *p; p++) { | 
179  |  |  | 
180  |  |         /* forced custom line breaks, not accounted as "normal" EOL */  | 
181  | 62.6M  |         if (linebreaks && strchr(linebreaks, *p)) { | 
182  | 160k  |             av_bprintf(buf, "\\N");  | 
183  |  |  | 
184  |  |         /* cancel curly brackets to avoid bogus override tag blocks  | 
185  |  |          * hiding text. Standard ASS has no character escapes,  | 
186  |  |          * though (only) libass provides \{ and \}. | 
187  |  |          * Unpaired closing brackets don't need escaping at all though and  | 
188  |  |          * to make the situation less bad in standard ASS insert an empty block  | 
189  |  |          */  | 
190  | 62.5M  |         } else if (!keep_ass_markup && *p == '{') { | 
191  | 27.8M  |             av_bprintf(buf, "\\{{}"); | 
192  |  |  | 
193  |  |         /* append word-joiner U+2060 as UTF-8 to break up sequences like \N */  | 
194  | 34.6M  |         } else if (!keep_ass_markup && *p == '\\') { | 
195  | 30.0M  |             if (p_end - p <= 3 || strncmp(p + 1, "\xe2\x81\xa0", 3))  | 
196  | 30.0M  |                 av_bprintf(buf, "\\\xe2\x81\xa0");  | 
197  | 12.2k  |             else  | 
198  | 12.2k  |                 av_bprintf(buf, "\\");  | 
199  |  |  | 
200  |  |         /* some packets might end abruptly (no \0 at the end, like for example  | 
201  |  |          * in some cases of demuxing from a classic video container), some  | 
202  |  |          * might be terminated with \n or \r\n which we have to remove (for  | 
203  |  |          * consistency with those who haven't), and we also have to deal with  | 
204  |  |          * evil cases such as \r at the end of the buffer (and no \0 terminated  | 
205  |  |          * character) */  | 
206  | 30.0M  |         } else if (p[0] == '\n') { | 
207  |  |             /* some stuff left so we can insert a line break */  | 
208  | 728k  |             if (p < p_end - 1)  | 
209  | 520k  |                 av_bprintf(buf, "\\N");  | 
210  | 3.89M  |         } else if (p[0] == '\r' && p < p_end - 1 && p[1] == '\n') { | 
211  |  |             /* \r followed by a \n, we can skip it. We don't insert the \N yet  | 
212  |  |              * because we don't know if it is followed by more text */  | 
213  | 1.26k  |             continue;  | 
214  |  |  | 
215  |  |         /* finally, a sane character */  | 
216  | 3.88M  |         } else { | 
217  | 3.88M  |             av_bprint_chars(buf, *p, 1);  | 
218  | 3.88M  |         }  | 
219  | 62.6M  |     }  | 
220  | 616k  | }  |