1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * SubRip subtitle muxer 3cabdff1aSopenharmony_ci * Copyright (c) 2012 Nicolas George <nicolas.george@normalesup.org> 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include "avformat.h" 23cabdff1aSopenharmony_ci#include "internal.h" 24cabdff1aSopenharmony_ci#include "libavutil/log.h" 25cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci/* TODO: add options for: 28cabdff1aSopenharmony_ci - character encoding; 29cabdff1aSopenharmony_ci - LF / CRLF; 30cabdff1aSopenharmony_ci - byte order mark. 31cabdff1aSopenharmony_ci */ 32cabdff1aSopenharmony_ci 33cabdff1aSopenharmony_citypedef struct SRTContext{ 34cabdff1aSopenharmony_ci unsigned index; 35cabdff1aSopenharmony_ci} SRTContext; 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_cistatic int srt_write_header(AVFormatContext *avf) 38cabdff1aSopenharmony_ci{ 39cabdff1aSopenharmony_ci SRTContext *srt = avf->priv_data; 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_ci if (avf->nb_streams != 1 || 42cabdff1aSopenharmony_ci avf->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) { 43cabdff1aSopenharmony_ci av_log(avf, AV_LOG_ERROR, 44cabdff1aSopenharmony_ci "SRT supports only a single subtitles stream.\n"); 45cabdff1aSopenharmony_ci return AVERROR(EINVAL); 46cabdff1aSopenharmony_ci } 47cabdff1aSopenharmony_ci if (avf->streams[0]->codecpar->codec_id != AV_CODEC_ID_TEXT && 48cabdff1aSopenharmony_ci avf->streams[0]->codecpar->codec_id != AV_CODEC_ID_SUBRIP) { 49cabdff1aSopenharmony_ci av_log(avf, AV_LOG_ERROR, 50cabdff1aSopenharmony_ci "Unsupported subtitles codec: %s\n", 51cabdff1aSopenharmony_ci avcodec_get_name(avf->streams[0]->codecpar->codec_id)); 52cabdff1aSopenharmony_ci return AVERROR(EINVAL); 53cabdff1aSopenharmony_ci } 54cabdff1aSopenharmony_ci avpriv_set_pts_info(avf->streams[0], 64, 1, 1000); 55cabdff1aSopenharmony_ci srt->index = 1; 56cabdff1aSopenharmony_ci return 0; 57cabdff1aSopenharmony_ci} 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_cistatic int srt_write_packet(AVFormatContext *avf, AVPacket *pkt) 60cabdff1aSopenharmony_ci{ 61cabdff1aSopenharmony_ci SRTContext *srt = avf->priv_data; 62cabdff1aSopenharmony_ci 63cabdff1aSopenharmony_ci int64_t s = pkt->pts, e, d = pkt->duration; 64cabdff1aSopenharmony_ci size_t size; 65cabdff1aSopenharmony_ci int x1 = -1, y1 = -1, x2 = -1, y2 = -1; 66cabdff1aSopenharmony_ci const uint8_t *p; 67cabdff1aSopenharmony_ci 68cabdff1aSopenharmony_ci p = av_packet_get_side_data(pkt, AV_PKT_DATA_SUBTITLE_POSITION, &size); 69cabdff1aSopenharmony_ci if (p && size == 16) { 70cabdff1aSopenharmony_ci x1 = AV_RL32(p ); 71cabdff1aSopenharmony_ci y1 = AV_RL32(p + 4); 72cabdff1aSopenharmony_ci x2 = AV_RL32(p + 8); 73cabdff1aSopenharmony_ci y2 = AV_RL32(p + 12); 74cabdff1aSopenharmony_ci } 75cabdff1aSopenharmony_ci 76cabdff1aSopenharmony_ci if (s == AV_NOPTS_VALUE || d < 0) { 77cabdff1aSopenharmony_ci av_log(avf, AV_LOG_WARNING, 78cabdff1aSopenharmony_ci "Insufficient timestamps in event number %d.\n", srt->index); 79cabdff1aSopenharmony_ci return 0; 80cabdff1aSopenharmony_ci } 81cabdff1aSopenharmony_ci e = s + d; 82cabdff1aSopenharmony_ci avio_printf(avf->pb, "%d\n%02d:%02d:%02d,%03d --> %02d:%02d:%02d,%03d", 83cabdff1aSopenharmony_ci srt->index, 84cabdff1aSopenharmony_ci (int)(s / 3600000), (int)(s / 60000) % 60, 85cabdff1aSopenharmony_ci (int)(s / 1000) % 60, (int)(s % 1000), 86cabdff1aSopenharmony_ci (int)(e / 3600000), (int)(e / 60000) % 60, 87cabdff1aSopenharmony_ci (int)(e / 1000) % 60, (int)(e % 1000)); 88cabdff1aSopenharmony_ci if (p) 89cabdff1aSopenharmony_ci avio_printf(avf->pb, " X1:%03d X2:%03d Y1:%03d Y2:%03d", 90cabdff1aSopenharmony_ci x1, x2, y1, y2); 91cabdff1aSopenharmony_ci avio_printf(avf->pb, "\n"); 92cabdff1aSopenharmony_ci 93cabdff1aSopenharmony_ci avio_write(avf->pb, pkt->data, pkt->size); 94cabdff1aSopenharmony_ci avio_write(avf->pb, "\n\n", 2); 95cabdff1aSopenharmony_ci srt->index++; 96cabdff1aSopenharmony_ci return 0; 97cabdff1aSopenharmony_ci} 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_ciconst AVOutputFormat ff_srt_muxer = { 100cabdff1aSopenharmony_ci .name = "srt", 101cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), 102cabdff1aSopenharmony_ci .mime_type = "application/x-subrip", 103cabdff1aSopenharmony_ci .extensions = "srt", 104cabdff1aSopenharmony_ci .priv_data_size = sizeof(SRTContext), 105cabdff1aSopenharmony_ci .write_header = srt_write_header, 106cabdff1aSopenharmony_ci .write_packet = srt_write_packet, 107cabdff1aSopenharmony_ci .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, 108cabdff1aSopenharmony_ci .subtitle_codec = AV_CODEC_ID_SUBRIP, 109cabdff1aSopenharmony_ci}; 110