1/* 2 * SubRip subtitle decoder 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 "config_components.h" 23 24#include "libavutil/avstring.h" 25#include "libavutil/common.h" 26#include "libavutil/intreadwrite.h" 27#include "libavutil/parseutils.h" 28#include "avcodec.h" 29#include "ass.h" 30#include "codec_internal.h" 31#include "htmlsubtitles.h" 32 33static int srt_to_ass(AVCodecContext *avctx, AVBPrint *dst, 34 const char *in, int x1, int y1, int x2, int y2) 35{ 36 if (x1 >= 0 && y1 >= 0) { 37 /* XXX: here we rescale coordinate assuming they are in DVD resolution 38 * (720x480) since we don't have anything better */ 39 40 if (x2 >= 0 && y2 >= 0 && (x2 != x1 || y2 != y1) && x2 >= x1 && y2 >= y1) { 41 /* text rectangle defined, write the text at the center of the rectangle */ 42 const int cx = x1 + (x2 - x1)/2; 43 const int cy = y1 + (y2 - y1)/2; 44 const int scaled_x = cx * (int64_t)ASS_DEFAULT_PLAYRESX / 720; 45 const int scaled_y = cy * (int64_t)ASS_DEFAULT_PLAYRESY / 480; 46 av_bprintf(dst, "{\\an5}{\\pos(%d,%d)}", scaled_x, scaled_y); 47 } else { 48 /* only the top left corner, assume the text starts in that corner */ 49 const int scaled_x = x1 * (int64_t)ASS_DEFAULT_PLAYRESX / 720; 50 const int scaled_y = y1 * (int64_t)ASS_DEFAULT_PLAYRESY / 480; 51 av_bprintf(dst, "{\\an1}{\\pos(%d,%d)}", scaled_x, scaled_y); 52 } 53 } 54 55 return ff_htmlmarkup_to_ass(avctx, dst, in); 56} 57 58static int srt_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, 59 int *got_sub_ptr, const AVPacket *avpkt) 60{ 61 AVBPrint buffer; 62 int x1 = -1, y1 = -1, x2 = -1, y2 = -1; 63 int ret; 64 size_t size; 65 const uint8_t *p = av_packet_get_side_data(avpkt, AV_PKT_DATA_SUBTITLE_POSITION, &size); 66 FFASSDecoderContext *s = avctx->priv_data; 67 68 if (p && size == 16) { 69 x1 = AV_RL32(p ); 70 y1 = AV_RL32(p + 4); 71 x2 = AV_RL32(p + 8); 72 y2 = AV_RL32(p + 12); 73 } 74 75 if (avpkt->size <= 0) 76 return avpkt->size; 77 78 av_bprint_init(&buffer, 0, AV_BPRINT_SIZE_UNLIMITED); 79 80 ret = srt_to_ass(avctx, &buffer, avpkt->data, x1, y1, x2, y2); 81 if (ret >= 0) 82 ret = ff_ass_add_rect(sub, buffer.str, s->readorder++, 0, NULL, NULL); 83 av_bprint_finalize(&buffer, NULL); 84 if (ret < 0) 85 return ret; 86 87 *got_sub_ptr = sub->num_rects > 0; 88 return avpkt->size; 89} 90 91#if CONFIG_SRT_DECODER 92/* deprecated decoder */ 93const FFCodec ff_srt_decoder = { 94 .p.name = "srt", 95 .p.long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), 96 .p.type = AVMEDIA_TYPE_SUBTITLE, 97 .p.id = AV_CODEC_ID_SUBRIP, 98 .init = ff_ass_subtitle_header_default, 99 FF_CODEC_DECODE_SUB_CB(srt_decode_frame), 100 .flush = ff_ass_decoder_flush, 101 .priv_data_size = sizeof(FFASSDecoderContext), 102 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 103}; 104#endif 105 106#if CONFIG_SUBRIP_DECODER 107const FFCodec ff_subrip_decoder = { 108 .p.name = "subrip", 109 .p.long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), 110 .p.type = AVMEDIA_TYPE_SUBTITLE, 111 .p.id = AV_CODEC_ID_SUBRIP, 112 .init = ff_ass_subtitle_header_default, 113 FF_CODEC_DECODE_SUB_CB(srt_decode_frame), 114 .flush = ff_ass_decoder_flush, 115 .priv_data_size = sizeof(FFASSDecoderContext), 116 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 117}; 118#endif 119