diff --git a/Changelog b/Changelog index fc5becb21d03eab7739033868db3d27673127b16..5bcb0da6f346c42035017da7fbadf1897f57b88f 100644 --- a/Changelog +++ b/Changelog @@ -27,6 +27,7 @@ version next: - iec61883 device - asettb filter - new option: -progress +- 3GPP Timed Text decoder version 0.11: diff --git a/doc/general.texi b/doc/general.texi index 4dea3f21790ff64713e4d3265178ba69ae7543f4..f390cb7a2f6423b47c680ba90fb2270836e43436 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -876,16 +876,17 @@ performance on systems without hardware floating point support). @multitable @columnfractions .4 .1 .1 .1 .1 @item Name @tab Muxing @tab Demuxing @tab Encoding @tab Decoding -@item SSA/ASS @tab X @tab X @tab X @tab X -@item DVB @tab X @tab X @tab X @tab X -@item DVD @tab X @tab X @tab X @tab X -@item JACOsub @tab X @tab X @tab @tab X -@item MicroDVD @tab X @tab X @tab @tab X -@item PGS @tab @tab @tab @tab X -@item RealText @tab @tab X @tab @tab X -@item SAMI @tab @tab X @tab @tab X -@item SubRip (SRT) @tab X @tab X @tab X @tab X -@item XSUB @tab @tab @tab X @tab X +@item SSA/ASS @tab X @tab X @tab X @tab X +@item DVB @tab X @tab X @tab X @tab X +@item DVD @tab X @tab X @tab X @tab X +@item JACOsub @tab X @tab X @tab @tab X +@item MicroDVD @tab X @tab X @tab @tab X +@item PGS @tab @tab @tab @tab X +@item RealText @tab @tab X @tab @tab X +@item SAMI @tab @tab X @tab @tab X +@item SubRip (SRT) @tab X @tab X @tab X @tab X +@item 3GPP Timed Text @tab @tab @tab @tab X +@item XSUB @tab @tab @tab X @tab X @end multitable @code{X} means that the feature is supported. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 10c602365728ccc17a21ae990890f65059a2e3ee..bbe188a7efd59ec529a497ec46f7248d4c7f5892 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -265,6 +265,7 @@ OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o mjpegdec.o mjpeg.o OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o OBJS-$(CONFIG_MMVIDEO_DECODER) += mmvideo.o OBJS-$(CONFIG_MOTIONPIXELS_DECODER) += motionpixels.o +OBJS-$(CONFIG_MOVTEXT_DECODER) += movtextdec.o ass.o OBJS-$(CONFIG_MP1_DECODER) += mpegaudiodec.o mpegaudiodecheader.o \ mpegaudio.o mpegaudiodata.o OBJS-$(CONFIG_MP1FLOAT_DECODER) += mpegaudiodec_float.o mpegaudiodecheader.o \ diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 52e7d204da67352b7dec501a2ae72957f4c143e7..963f1a5cac9f5aa7ffc12d701d37bd579a6756aa 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -409,6 +409,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (DVDSUB, dvdsub); REGISTER_DECODER (JACOSUB, jacosub); REGISTER_DECODER (MICRODVD, microdvd); + REGISTER_DECODER (MOVTEXT, movtext); REGISTER_DECODER (PGSSUB, pgssub); REGISTER_DECODER (REALTEXT, realtext); REGISTER_DECODER (SAMI, sami); diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c new file mode 100644 index 0000000000000000000000000000000000000000..43ebb789d614aaf1d8fc9ab8bfcfd9ef561d89b0 --- /dev/null +++ b/libavcodec/movtextdec.c @@ -0,0 +1,106 @@ +/* + * 3GPP TS 26.245 Timed Text decoder + * Copyright (c) 2012 Philip Langdale <philipl@overt.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" +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/bprint.h" +#include "libavutil/intreadwrite.h" + +static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end) +{ + while (text < text_end) { + switch (*text) { + case '\r': + break; + case '\n': + av_bprintf(buf, "\\N"); + break; + default: + av_bprint_chars(buf, *text, 1); + break; + } + text++; + } + + av_bprintf(buf, "\r\n"); + return 0; +} + +static int mov_text_init(AVCodecContext *avctx) { + /* + * TODO: Handle the default text style. + * NB: Most players ignore styles completely, with the result that + * it's very common to find files where the default style is broken + * and respecting it results in a worse experience than ignoring it. + */ + return ff_ass_subtitle_header_default(avctx); +} + +static int mov_text_decode_frame(AVCodecContext *avctx, + void *data, int *got_sub_ptr, AVPacket *avpkt) +{ + AVSubtitle *sub = data; + int ts_start, ts_end; + AVBPrint buf; + const char *ptr = avpkt->data; + const char *end; + + if (!ptr || avpkt->size <= 2) + return 0; + + /* + * The first two bytes of the packet are the length of the text string + * In complex cases, there are style descriptors appended to the string + * so we can't just assume the packet size is the string size. + */ + end = ptr + FFMAX(2 + AV_RB16(ptr), avpkt->size); + ptr += 2; + + ts_start = av_rescale_q(avpkt->pts, + avctx->time_base, + (AVRational){1,100}); + ts_end = av_rescale_q(avpkt->pts + avpkt->duration, + avctx->time_base, + (AVRational){1,100}); + + // Note that the spec recommends lines be no longer than 2048 characters. + av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); + text_to_ass(&buf, ptr, end); + + if (!av_bprint_is_complete(&buf)) + return AVERROR(ENOMEM); + + ff_ass_add_rect(sub, buf.str, ts_start, ts_end-ts_start, 0); + *got_sub_ptr = sub->num_rects > 0; + av_bprint_finalize(&buf, NULL); + return avpkt->size; +} + +AVCodec ff_movtext_decoder = { + .name = "mov_text", + .long_name = NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = CODEC_ID_MOV_TEXT, + .init = mov_text_init, + .decode = mov_text_decode_frame, +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index a76c7f9207348e2c743a07ae96d3697c5ae64856..05ee7a9f43d7a11a9218c71fcc3735ecfe41b1f3 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -27,7 +27,7 @@ */ #define LIBAVCODEC_VERSION_MAJOR 54 -#define LIBAVCODEC_VERSION_MINOR 38 +#define LIBAVCODEC_VERSION_MINOR 39 #define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak index f2a68e11071046888b926caef6be9307b483cad1..92322da6f1ee57e3cd03279f4da50d58eff8d8a5 100644 --- a/tests/fate/subtitles.mak +++ b/tests/fate/subtitles.mak @@ -13,5 +13,8 @@ fate-sub-srt: CMD = md5 -i $(SAMPLES)/sub/SubRip_capability_tester.srt -f ass FATE_SUBTITLES += fate-sub-realtext fate-sub-realtext: CMD = md5 -i $(SAMPLES)/sub/RealText_capability_tester.rt -f ass +FATE_SUBTITLES += fate-sub-movtext +fate-sub-movtext: CMD = md5 -i $(SAMPLES)/sub/MovText_capability_tester.mp4 -f ass + FATE_SAMPLES_FFMPEG += $(FATE_SUBTITLES) fate-subtitles: $(FATE_SUBTITLES) diff --git a/tests/ref/fate/sub-movtext b/tests/ref/fate/sub-movtext new file mode 100644 index 0000000000000000000000000000000000000000..d91c24303c42418f5f6ee3ee80f889aed6ed057e --- /dev/null +++ b/tests/ref/fate/sub-movtext @@ -0,0 +1 @@ +21453e8ddbbe35d1368a99fe563c969d