From 9e63c30daa8bfde52c534027ce984e8cf3f200c3 Mon Sep 17 00:00:00 2001 From: Nicolas George Date: Sun, 17 Jun 2012 21:11:49 +0200 Subject: [PATCH] lavf: add a real SRT muxer. This muxer supports CODEC_ID_SRT with the timestamps in the packet data and CODEC_ID_TEXT with the timestamps in the packet fields. Makes -scodec copy work from Matroska. --- libavformat/Makefile | 2 +- libavformat/rawenc.c | 12 ------ libavformat/srtenc.c | 99 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 13 deletions(-) create mode 100644 libavformat/srtenc.c diff --git a/libavformat/Makefile b/libavformat/Makefile index 74257392cd..9032654ae5 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -313,7 +313,7 @@ OBJS-$(CONFIG_SOX_MUXER) += soxenc.o OBJS-$(CONFIG_SPDIF_DEMUXER) += spdif.o spdifdec.o OBJS-$(CONFIG_SPDIF_MUXER) += spdif.o spdifenc.o OBJS-$(CONFIG_SRT_DEMUXER) += srtdec.o -OBJS-$(CONFIG_SRT_MUXER) += rawenc.o +OBJS-$(CONFIG_SRT_MUXER) += srtenc.o OBJS-$(CONFIG_STR_DEMUXER) += psxstr.o OBJS-$(CONFIG_SWF_DEMUXER) += swfdec.o OBJS-$(CONFIG_SWF_MUXER) += swfenc.o diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c index 3745620133..8be3cc999e 100644 --- a/libavformat/rawenc.c +++ b/libavformat/rawenc.c @@ -257,18 +257,6 @@ AVOutputFormat ff_rawvideo_muxer = { }; #endif -#if CONFIG_SRT_MUXER -AVOutputFormat ff_srt_muxer = { - .name = "srt", - .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle format"), - .mime_type = "application/x-subrip", - .extensions = "srt", - .write_packet = ff_raw_write_packet, - .flags = AVFMT_NOTIMESTAMPS, - .subtitle_codec = CODEC_ID_SRT, -}; -#endif - #if CONFIG_TRUEHD_MUXER AVOutputFormat ff_truehd_muxer = { .name = "truehd", diff --git a/libavformat/srtenc.c b/libavformat/srtenc.c new file mode 100644 index 0000000000..b8fc8fac7e --- /dev/null +++ b/libavformat/srtenc.c @@ -0,0 +1,99 @@ +/* + * SubRip subtitle muxer + * Copyright (c) 2012 Nicolas George + * + * 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 "avformat.h" +#include "internal.h" +#include "libavutil/log.h" + +/* TODO: add options for: + - character encoding; + - LF / CRLF; + - byte order mark. + */ + +typedef struct SRTContext{ + unsigned index; +} SRTContext; + +static int srt_write_header(AVFormatContext *avf) +{ + if (avf->nb_streams != 1 || + avf->streams[0]->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) { + av_log(avf, AV_LOG_ERROR, + "SRT supports only a single subtitles stream.\n"); + return AVERROR(EINVAL); + } + if (avf->streams[0]->codec->codec_id != CODEC_ID_TEXT && + avf->streams[0]->codec->codec_id != CODEC_ID_SRT) { + av_log(avf, AV_LOG_ERROR, + "Unsupported subtitles codec: %s\n", + avcodec_get_name(avf->streams[0]->codec->codec_id)); + return AVERROR(EINVAL); + } + avpriv_set_pts_info(avf->streams[0], 64, 1, 1000); + return 0; +} + +static int srt_write_packet(AVFormatContext *avf, AVPacket *pkt) +{ + SRTContext *srt = avf->priv_data; + int write_ts = avf->streams[0]->codec->codec_id != CODEC_ID_SRT; + + srt->index++; + if (write_ts) { + char buf[64]; + int64_t s = pkt->pts, e, d = pkt->duration; + int len; + + if (d <= 0) + d = pkt->convergence_duration; + if (s == AV_NOPTS_VALUE || d <= 0) { + av_log(avf, AV_LOG_ERROR, "Insufficient timestamps.\n"); + return AVERROR(EINVAL); + } + e = s + d; + len = snprintf(buf, sizeof(buf), + "%d\n%02d:%02d:%02d,%03d --> %02d:%02d:%02d,%03d\n", + srt->index, + (int)(s / 3600000), (int)(s / 60000) % 60, + (int)(s / 1000) % 60, (int)(s % 1000), + (int)(e / 3600000), (int)(e / 60000) % 60, + (int)(e / 1000) % 60, (int)(e % 1000)); + avio_write(avf->pb, buf, len); + } + avio_write(avf->pb, pkt->data, pkt->size); + if (write_ts) + avio_write(avf->pb, "\n\n", 2); + avio_flush(avf->pb); + return 0; +} + +AVOutputFormat ff_srt_muxer = { + .name = "srt", + .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle format"), + .mime_type = "application/x-subrip", + .extensions = "srt", + .priv_data_size = sizeof(SRTContext), + .write_header = srt_write_header, + .write_packet = srt_write_packet, + .flags = AVFMT_VARIABLE_FPS, + .subtitle_codec = CODEC_ID_TEXT, +};