FFmpeg
webvttdec.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012 Clément Bœsch
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /**
22  * @file
23  * WebVTT subtitle decoder
24  * @see http://dev.w3.org/html5/webvtt/
25  * @todo need to support extended markups and cue settings
26  */
27 
28 #include "avcodec.h"
29 #include "ass.h"
30 #include "codec_internal.h"
31 #include "libavutil/bprint.h"
32 
33 static const struct {
34  const char *from;
35  const char *to;
36 } webvtt_tag_replace[] = {
37  {"<i>", "{\\i1}"}, {"</i>", "{\\i0}"},
38  {"<b>", "{\\b1}"}, {"</b>", "{\\b0}"},
39  {"<u>", "{\\u1}"}, {"</u>", "{\\u0}"},
40  {"{", "\\{"}, {"}", "\\}"}, // escape to avoid ASS markup conflicts
41  {"&gt;", ">"}, {"&lt;", "<"},
42  {"&lrm;", ""}, {"&rlm;", ""}, // FIXME: properly honor bidi marks
43  {"&amp;", "&"}, {"&nbsp;", "\\h"},
44 };
45 
46 static int webvtt_event_to_ass(AVBPrint *buf, const char *p)
47 {
48  int i, again = 0, skip = 0;
49 
50  while (*p) {
51 
52  for (i = 0; i < FF_ARRAY_ELEMS(webvtt_tag_replace); i++) {
53  const char *from = webvtt_tag_replace[i].from;
54  const size_t len = strlen(from);
55  if (!strncmp(p, from, len)) {
56  av_bprintf(buf, "%s", webvtt_tag_replace[i].to);
57  p += len;
58  again = 1;
59  break;
60  }
61  }
62  if (!*p)
63  break;
64 
65  if (again) {
66  again = 0;
67  skip = 0;
68  continue;
69  }
70  if (*p == '<')
71  skip = 1;
72  else if (*p == '>')
73  skip = 0;
74  else if (p[0] == '\n' && p[1])
75  av_bprintf(buf, "\\N");
76  else if (!skip && *p != '\r')
77  av_bprint_chars(buf, *p, 1);
78  p++;
79  }
80  return 0;
81 }
82 
84  int *got_sub_ptr, const AVPacket *avpkt)
85 {
86  int ret = 0;
87  const char *ptr = avpkt->data;
89  AVBPrint buf;
90 
92  if (ptr && avpkt->size > 0 && !webvtt_event_to_ass(&buf, ptr))
93  ret = ff_ass_add_rect(sub, buf.str, s->readorder++, 0, NULL, NULL);
94  av_bprint_finalize(&buf, NULL);
95  if (ret < 0)
96  return ret;
97  *got_sub_ptr = sub->num_rects > 0;
98  return avpkt->size;
99 }
100 
102  .p.name = "webvtt",
103  .p.long_name = NULL_IF_CONFIG_SMALL("WebVTT subtitle"),
104  .p.type = AVMEDIA_TYPE_SUBTITLE,
105  .p.id = AV_CODEC_ID_WEBVTT,
108  .flush = ff_ass_decoder_flush,
109  .priv_data_size = sizeof(FFASSDecoderContext),
110  .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
111 };
AVSubtitle
Definition: avcodec.h:2305
AVMEDIA_TYPE_SUBTITLE
@ AVMEDIA_TYPE_SUBTITLE
Definition: avutil.h:204
AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_UNLIMITED
ff_ass_subtitle_header_default
int ff_ass_subtitle_header_default(AVCodecContext *avctx)
Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS with default style.
Definition: ass.c:96
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
webvtt_event_to_ass
static int webvtt_event_to_ass(AVBPrint *buf, const char *p)
Definition: webvttdec.c:46
sub
static float sub(float src0, float src1)
Definition: dnn_backend_native_layer_mathbinary.c:31
ff_webvtt_decoder
const FFCodec ff_webvtt_decoder
Definition: webvttdec.c:101
ff_ass_add_rect
int ff_ass_add_rect(AVSubtitle *sub, const char *dialog, int readorder, int layer, const char *style, const char *speaker)
Add an ASS dialog to a subtitle.
Definition: ass.c:157
AVPacket::data
uint8_t * data
Definition: packet.h:374
webvtt_decode_frame
static int webvtt_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, int *got_sub_ptr, const AVPacket *avpkt)
Definition: webvttdec.c:83
FFCodec
Definition: codec_internal.h:112
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:116
ass.h
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
s
#define s(width, name)
Definition: cbs_vp9.c:256
to
const char * to
Definition: webvttdec.c:35
AV_CODEC_ID_WEBVTT
@ AV_CODEC_ID_WEBVTT
Definition: codec_id.h:545
NULL
#define NULL
Definition: coverity.c:32
from
const char * from
Definition: webvttdec.c:34
AVPacket::size
int size
Definition: packet.h:375
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
codec_internal.h
webvtt_tag_replace
static const struct @190 webvtt_tag_replace[]
ff_ass_decoder_flush
void ff_ass_decoder_flush(AVCodecContext *avctx)
Helper to flush a text subtitles decoder making use of the FFASSDecoderContext.
Definition: ass.c:164
bprint.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
FF_CODEC_CAP_INIT_THREADSAFE
#define FF_CODEC_CAP_INIT_THREADSAFE
The codec does not modify any global variables in the init function, allowing to call the init functi...
Definition: codec_internal.h:31
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:203
len
int len
Definition: vorbis_enc_data.h:426
avcodec.h
ret
ret
Definition: filter_design.txt:187
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:94
AVCodecContext
main external API structure.
Definition: avcodec.h:389
again
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining again
Definition: filter_design.txt:25
FF_CODEC_DECODE_SUB_CB
#define FF_CODEC_DECODE_SUB_CB(func)
Definition: codec_internal.h:257
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:416
AVPacket
This structure stores compressed data.
Definition: packet.h:351
FFASSDecoderContext
Definition: ass.h:46
av_bprint_chars
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
Append char c n times to a print buffer.
Definition: bprint.c:140