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