Originally committed as revision 25747 to svn://svn.ffmpeg.org/ffmpeg/trunk
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,68 @@ |
| 0 |
+/* |
|
| 1 |
+ * SSA/ASS common funtions |
|
| 2 |
+ * Copyright (c) 2010 Aurelien Jacobs <aurel@gnuage.org> |
|
| 3 |
+ * |
|
| 4 |
+ * This file is part of FFmpeg. |
|
| 5 |
+ * |
|
| 6 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
| 7 |
+ * modify it under the terms of the GNU Lesser General Public |
|
| 8 |
+ * License as published by the Free Software Foundation; either |
|
| 9 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
| 10 |
+ * |
|
| 11 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
| 12 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 13 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
| 14 |
+ * Lesser General Public License for more details. |
|
| 15 |
+ * |
|
| 16 |
+ * You should have received a copy of the GNU Lesser General Public |
|
| 17 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
| 18 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
| 19 |
+ */ |
|
| 20 |
+ |
|
| 21 |
+#include "avcodec.h" |
|
| 22 |
+#include "ass.h" |
|
| 23 |
+ |
|
| 24 |
+void ff_ass_init(AVSubtitle *sub) |
|
| 25 |
+{
|
|
| 26 |
+ memset(sub, 0, sizeof(*sub)); |
|
| 27 |
+} |
|
| 28 |
+ |
|
| 29 |
+static int ts_to_string(char *str, int strlen, int ts) |
|
| 30 |
+{
|
|
| 31 |
+ int h, m, s; |
|
| 32 |
+ h = ts/360000; ts -= 360000*h; |
|
| 33 |
+ m = ts/ 6000; ts -= 6000*m; |
|
| 34 |
+ s = ts/ 100; ts -= 100*s; |
|
| 35 |
+ return snprintf(str, strlen, "%d:%02d:%02d.%02d", h, m, s, ts); |
|
| 36 |
+} |
|
| 37 |
+ |
|
| 38 |
+int ff_ass_add_rect(AVSubtitle *sub, const char *dialog, |
|
| 39 |
+ int ts_start, int ts_end, int raw) |
|
| 40 |
+{
|
|
| 41 |
+ int len = 0, dlen, duration = ts_end - ts_start; |
|
| 42 |
+ char s_start[16], s_end[16], header[48] = {0};
|
|
| 43 |
+ AVSubtitleRect **rects; |
|
| 44 |
+ |
|
| 45 |
+ if (!raw) {
|
|
| 46 |
+ ts_to_string(s_start, sizeof(s_start), ts_start); |
|
| 47 |
+ ts_to_string(s_end, sizeof(s_end), ts_end ); |
|
| 48 |
+ len = snprintf(header, sizeof(header), "Dialogue: 0,%s,%s,", |
|
| 49 |
+ s_start, s_end); |
|
| 50 |
+ } |
|
| 51 |
+ |
|
| 52 |
+ dlen = strcspn(dialog, "\n"); |
|
| 53 |
+ dlen += dialog[dlen] == '\n'; |
|
| 54 |
+ |
|
| 55 |
+ rects = av_realloc(sub->rects, (sub->num_rects+1) * sizeof(*sub->rects)); |
|
| 56 |
+ if (!rects) |
|
| 57 |
+ return AVERROR(ENOMEM); |
|
| 58 |
+ sub->rects = rects; |
|
| 59 |
+ sub->end_display_time = FFMAX(sub->end_display_time, 10 * duration); |
|
| 60 |
+ rects[sub->num_rects] = av_mallocz(sizeof(*rects[0])); |
|
| 61 |
+ rects[sub->num_rects]->type = SUBTITLE_ASS; |
|
| 62 |
+ rects[sub->num_rects]->ass = av_malloc(len + dlen + 1); |
|
| 63 |
+ strcpy (rects[sub->num_rects]->ass , header); |
|
| 64 |
+ strncpy(rects[sub->num_rects]->ass + len, dialog, dlen); |
|
| 65 |
+ sub->num_rects++; |
|
| 66 |
+ return dlen; |
|
| 67 |
+} |
| 0 | 68 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,53 @@ |
| 0 |
+/* |
|
| 1 |
+ * SSA/ASS common funtions |
|
| 2 |
+ * Copyright (c) 2010 Aurelien Jacobs <aurel@gnuage.org> |
|
| 3 |
+ * |
|
| 4 |
+ * This file is part of FFmpeg. |
|
| 5 |
+ * |
|
| 6 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
| 7 |
+ * modify it under the terms of the GNU Lesser General Public |
|
| 8 |
+ * License as published by the Free Software Foundation; either |
|
| 9 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
| 10 |
+ * |
|
| 11 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
| 12 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 13 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
| 14 |
+ * Lesser General Public License for more details. |
|
| 15 |
+ * |
|
| 16 |
+ * You should have received a copy of the GNU Lesser General Public |
|
| 17 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
| 18 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
| 19 |
+ */ |
|
| 20 |
+ |
|
| 21 |
+#ifndef AVCODEC_ASS_H |
|
| 22 |
+#define AVCODEC_ASS_H |
|
| 23 |
+ |
|
| 24 |
+#include "avcodec.h" |
|
| 25 |
+ |
|
| 26 |
+/** |
|
| 27 |
+ * Initialize an AVSubtitle structure for use with ff_ass_add_rect(). |
|
| 28 |
+ * |
|
| 29 |
+ * @param sub pointer to the AVSubtitle |
|
| 30 |
+ */ |
|
| 31 |
+void ff_ass_init(AVSubtitle *sub); |
|
| 32 |
+ |
|
| 33 |
+/** |
|
| 34 |
+ * Add an ASS dialog line to an AVSubtitle as a new AVSubtitleRect. |
|
| 35 |
+ * |
|
| 36 |
+ * @param sub pointer to the AVSubtitle |
|
| 37 |
+ * @param dialog ASS dialog to add to sub |
|
| 38 |
+ * @param ts_start start timestamp for this dialog (in 1/100 second unit) |
|
| 39 |
+ * @param ts_end end timestamp for this dialog (in 1/100 second unit) |
|
| 40 |
+ * @param raw when set to 1, it indicates that dialog contains a whole ASS |
|
| 41 |
+ * dialog line which should be copied as is. |
|
| 42 |
+ * when set to 0, it indicates that dialog contains only the Text |
|
| 43 |
+ * part of the ASS dialog line, the rest of the line |
|
| 44 |
+ * will be generated. |
|
| 45 |
+ * @return number of characters read from dialog. It can be less than the whole |
|
| 46 |
+ * length of dialog, if dialog contains several lines of text. |
|
| 47 |
+ * A negative value indicates an error. |
|
| 48 |
+ */ |
|
| 49 |
+int ff_ass_add_rect(AVSubtitle *sub, const char *dialog, |
|
| 50 |
+ int ts_start, int ts_end, int raw); |
|
| 51 |
+ |
|
| 52 |
+#endif /* AVCODEC_ASS_H */ |
| 0 | 53 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,62 @@ |
| 0 |
+/* |
|
| 1 |
+ * SSA/ASS decoder |
|
| 2 |
+ * Copyright (c) 2010 Aurelien Jacobs <aurel@gnuage.org> |
|
| 3 |
+ * |
|
| 4 |
+ * This file is part of FFmpeg. |
|
| 5 |
+ * |
|
| 6 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
| 7 |
+ * modify it under the terms of the GNU Lesser General Public |
|
| 8 |
+ * License as published by the Free Software Foundation; either |
|
| 9 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
| 10 |
+ * |
|
| 11 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
| 12 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 13 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
| 14 |
+ * Lesser General Public License for more details. |
|
| 15 |
+ * |
|
| 16 |
+ * You should have received a copy of the GNU Lesser General Public |
|
| 17 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
| 18 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
| 19 |
+ */ |
|
| 20 |
+ |
|
| 21 |
+#include "avcodec.h" |
|
| 22 |
+#include "ass.h" |
|
| 23 |
+ |
|
| 24 |
+static av_cold int ass_decode_init(AVCodecContext *avctx) |
|
| 25 |
+{
|
|
| 26 |
+ avctx->subtitle_header = av_malloc(avctx->extradata_size); |
|
| 27 |
+ if (!avctx->extradata) |
|
| 28 |
+ return AVERROR(ENOMEM); |
|
| 29 |
+ memcpy(avctx->subtitle_header, avctx->extradata, avctx->extradata_size); |
|
| 30 |
+ avctx->subtitle_header_size = avctx->extradata_size; |
|
| 31 |
+ return 0; |
|
| 32 |
+} |
|
| 33 |
+ |
|
| 34 |
+static int ass_decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, |
|
| 35 |
+ AVPacket *avpkt) |
|
| 36 |
+{
|
|
| 37 |
+ const char *ptr = avpkt->data; |
|
| 38 |
+ int len, size = avpkt->size; |
|
| 39 |
+ |
|
| 40 |
+ ff_ass_init(data); |
|
| 41 |
+ |
|
| 42 |
+ while (size > 0) {
|
|
| 43 |
+ len = ff_ass_add_rect(data, ptr, 0, 0/* FIXME: duration */, 1); |
|
| 44 |
+ if (len < 0) |
|
| 45 |
+ return len; |
|
| 46 |
+ ptr += len; |
|
| 47 |
+ size -= len; |
|
| 48 |
+ } |
|
| 49 |
+ |
|
| 50 |
+ *got_sub_ptr = avpkt->size > 0; |
|
| 51 |
+ return avpkt->size; |
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+AVCodec ass_decoder = {
|
|
| 55 |
+ .name = "ass", |
|
| 56 |
+ .long_name = NULL_IF_CONFIG_SMALL("Advanced SubStation Alpha subtitle"),
|
|
| 57 |
+ .type = AVMEDIA_TYPE_SUBTITLE, |
|
| 58 |
+ .id = CODEC_ID_SSA, |
|
| 59 |
+ .init = ass_decode_init, |
|
| 60 |
+ .decode = ass_decode_frame, |
|
| 61 |
+}; |
| 0 | 62 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,67 @@ |
| 0 |
+/* |
|
| 1 |
+ * SSA/ASS encoder |
|
| 2 |
+ * Copyright (c) 2010 Aurelien Jacobs <aurel@gnuage.org> |
|
| 3 |
+ * |
|
| 4 |
+ * This file is part of FFmpeg. |
|
| 5 |
+ * |
|
| 6 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
| 7 |
+ * modify it under the terms of the GNU Lesser General Public |
|
| 8 |
+ * License as published by the Free Software Foundation; either |
|
| 9 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
| 10 |
+ * |
|
| 11 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
| 12 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 13 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
| 14 |
+ * Lesser General Public License for more details. |
|
| 15 |
+ * |
|
| 16 |
+ * You should have received a copy of the GNU Lesser General Public |
|
| 17 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
| 18 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
| 19 |
+ */ |
|
| 20 |
+ |
|
| 21 |
+#include "avcodec.h" |
|
| 22 |
+#include "libavutil/avstring.h" |
|
| 23 |
+ |
|
| 24 |
+static av_cold int ass_encode_init(AVCodecContext *avctx) |
|
| 25 |
+{
|
|
| 26 |
+ avctx->extradata = av_malloc(avctx->subtitle_header_size); |
|
| 27 |
+ if (!avctx->extradata) |
|
| 28 |
+ return AVERROR(ENOMEM); |
|
| 29 |
+ memcpy(avctx->extradata, avctx->subtitle_header, avctx->subtitle_header_size); |
|
| 30 |
+ avctx->extradata_size = avctx->subtitle_header_size; |
|
| 31 |
+ return 0; |
|
| 32 |
+} |
|
| 33 |
+ |
|
| 34 |
+static int ass_encode_frame(AVCodecContext *avctx, |
|
| 35 |
+ unsigned char *buf, int bufsize, void *data) |
|
| 36 |
+{
|
|
| 37 |
+ AVSubtitle *sub = data; |
|
| 38 |
+ int i, len, total_len = 0; |
|
| 39 |
+ |
|
| 40 |
+ for (i=0; i<sub->num_rects; i++) {
|
|
| 41 |
+ if (sub->rects[i]->type != SUBTITLE_ASS) {
|
|
| 42 |
+ av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n"); |
|
| 43 |
+ return -1; |
|
| 44 |
+ } |
|
| 45 |
+ |
|
| 46 |
+ len = av_strlcpy(buf+total_len, sub->rects[i]->ass, bufsize-total_len); |
|
| 47 |
+ |
|
| 48 |
+ if (len > bufsize-total_len-1) {
|
|
| 49 |
+ av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n"); |
|
| 50 |
+ return -1; |
|
| 51 |
+ } |
|
| 52 |
+ |
|
| 53 |
+ total_len += len; |
|
| 54 |
+ } |
|
| 55 |
+ |
|
| 56 |
+ return total_len; |
|
| 57 |
+} |
|
| 58 |
+ |
|
| 59 |
+AVCodec ass_encoder = {
|
|
| 60 |
+ .name = "ass", |
|
| 61 |
+ .long_name = NULL_IF_CONFIG_SMALL("Advanced SubStation Alpha subtitle"),
|
|
| 62 |
+ .type = AVMEDIA_TYPE_SUBTITLE, |
|
| 63 |
+ .id = CODEC_ID_SSA, |
|
| 64 |
+ .init = ass_encode_init, |
|
| 65 |
+ .encode = ass_encode_frame, |
|
| 66 |
+}; |