[FFmpeg-devel] [PATCH] Add MPL2 subtitles demuxer and decoder.
Clément Bœsch
ubitux at gmail.com
Sat Dec 29 19:18:45 CET 2012
On Sat, Dec 29, 2012 at 12:45:18PM +0100, Stefano Sabatini wrote:
[...]
> > +/**
> > + * @file
> > + * MPL2 subtitles decoder
>
> maybe mention a spec or some doc here, for example this one:
> http://web.archive.org/web/20090328040233/http://napisy.ussbrowarek.org/mpl2-eng.html
>
Yep, I thought I added this link…
> > + */
> > +
> > +#include "avcodec.h"
> > +#include "ass.h"
> > +#include "libavutil/bprint.h"
> > +
> > +static int mpl2_event_to_ass(AVBPrint *buf, const char *p)
> > +{
> > + if (*p == ' ')
> > + p++;
> > +
> > + while (*p) {
> > + int got_style = 0;
> > +
> > + while (*p && strchr("/\\_", *p)) {
> > + if (*p == '/') av_bprintf(buf, "{\\i1}");
> > + else if (*p == '\\') av_bprintf(buf, "{\\b1}");
> > + else if (*p == '_') av_bprintf(buf, "{\\u1}");
> > + got_style = 1;
> > + p++;
> > + }
> > +
> > + while (*p && *p != '|') {
> > + if (*p != '\r' && *p != '\n')
> > + av_bprint_chars(buf, *p, 1);
> > + p++;
> > + }
> > +
> > + if (*p == '|') {
> > + if (got_style)
> > + av_bprintf(buf, "{\\r}");
> > + av_bprintf(buf, "\\N");
> > + p++;
> > + }
> > + }
> > +
> > + av_bprintf(buf, "\r\n");
> > + return 0;
> > +}
> > +
>
> > +static int mpl2_decode_frame(AVCodecContext *avctx, void *data,
> > + int *got_sub_ptr, AVPacket *avpkt)
> > +{
> > + AVBPrint buf;
> > + AVSubtitle *sub = data;
> > + const char *ptr = avpkt->data;
> > + const int ts_start = av_rescale_q(avpkt->pts, avctx->time_base, (AVRational){1,100});
>
> > + const int ts_duration = avpkt->duration != -1 ?
>
> is -1 allowed? I ask because I can't find it specified in avcodec.h.
>
It's only used for ff_ass_add_rect(), and it's a special case for the
latest event.
[...]
> > +static int read_ts(char **line, int64_t *pts_start, int *duration)
> > +{
> > + char c;
> > + int len;
> > + int64_t end;
> > +
> > + if (sscanf(*line, "[%"PRId64"][]%c%n",
> > + pts_start, &c, &len) >= 2) {
> > + *duration = -1;
>
> > + *line += len - 1;
> > + return 0;
> > + }
> > + if (sscanf(*line, "[%"PRId64"][%"PRId64"]%c%n",
> > + pts_start, &end, &c, &len) >= 3) {
> > + *duration = end - *pts_start;
>
> > + *line += len - 1;
> > + return 0;
>
> Nit: this can be factorized (if it is worth the trouble)
>
I can rewrite that if people want, but I don't think it's worth the
trouble.
> > + }
> > + return -1;
> > +}
> > +
> > +static int mpl2_read_header(AVFormatContext *s)
> > +{
> > + MPL2Context *mpl2 = s->priv_data;
> > + AVStream *st = avformat_new_stream(s, NULL);
> > + int res = 0;
> > +
> > + if (!st)
> > + return AVERROR(ENOMEM);
> > + avpriv_set_pts_info(st, 64, 1, 10);
> > + st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
> > + st->codec->codec_id = AV_CODEC_ID_MPL2;
> > +
> > + while (!url_feof(s->pb)) {
> > + char line[4096];
> > + char *p = line;
> > + const int64_t pos = avio_tell(s->pb);
> > + int len = ff_get_line(s->pb, line, sizeof(line));
>
> Nit: you could add a warning in case the line is truncated (not sure
> you can really check it in an efficient way)
>
I don't think we ever did that…
> > + int64_t pts_start;
> > + int duration;
> > +
> > + if (!len)
> > + break;
> > +
> > + line[strcspn(line, "\r\n")] = 0;
> > +
> > + if (!read_ts(&p, &pts_start, &duration)) {
>
> Nit++: read_ts(...) >= 0?
>
If you prefer…
> > + AVPacket *sub;
> > +
> > + sub = ff_subtitles_queue_insert(&mpl2->q, p, strlen(p), 0);
> > + if (!sub)
> > + return AVERROR(ENOMEM);
> > + sub->pos = pos;
> > + sub->pts = pts_start;
> > + sub->duration = duration;
> > + }
> > + }
> > +
> > + ff_subtitles_queue_finalize(&mpl2->q);
> > + return res;
> > +}
> > +
> > +static int mpl2_read_packet(AVFormatContext *s, AVPacket *pkt)
> > +{
> > + MPL2Context *mpl2 = s->priv_data;
> > + return ff_subtitles_queue_read_packet(&mpl2->q, pkt);
> > +}
> > +
> > +static int mpl2_read_seek(AVFormatContext *s, int stream_index,
> > + int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
> > +{
> > + MPL2Context *mpl2 = s->priv_data;
> > + return ff_subtitles_queue_seek(&mpl2->q, s, stream_index,
> > + min_ts, ts, max_ts, flags);
> > +}
> > +
> > +static int mpl2_read_close(AVFormatContext *s)
> > +{
> > + MPL2Context *mpl2 = s->priv_data;
> > + ff_subtitles_queue_clean(&mpl2->q);
> > + return 0;
> > +}
> > +
> > +AVInputFormat ff_mpl2_demuxer = {
> > + .name = "mpl2",
> > + .long_name = NULL_IF_CONFIG_SMALL("MPL2 subtitles"),
> > + .priv_data_size = sizeof(MPL2Context),
> > + .read_probe = mpl2_probe,
> > + .read_header = mpl2_read_header,
> > + .read_packet = mpl2_read_packet,
> > + .read_seek2 = mpl2_read_seek,
> > + .read_close = mpl2_read_close,
> > + .extensions = "txt,mpl2",
> > +};
> > diff --git a/libavformat/version.h b/libavformat/version.h
> > index bd14e56..8a22dd4 100644
> > --- a/libavformat/version.h
> > +++ b/libavformat/version.h
> > @@ -30,8 +30,8 @@
> > #include "libavutil/avutil.h"
> >
> > #define LIBAVFORMAT_VERSION_MAJOR 54
> > -#define LIBAVFORMAT_VERSION_MINOR 50
> > -#define LIBAVFORMAT_VERSION_MICRO 102
> > +#define LIBAVFORMAT_VERSION_MINOR 51
> > +#define LIBAVFORMAT_VERSION_MICRO 100
> >
> > #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
> > LIBAVFORMAT_VERSION_MINOR, \
> > diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak
> > index 55c9557..9934ddf 100644
> > --- a/tests/fate/subtitles.mak
> > +++ b/tests/fate/subtitles.mak
> > @@ -10,6 +10,9 @@ fate-sub-movtext: CMD = md5 -i $(SAMPLES)/sub/MovText_capability_tester.mp4 -f a
> > FATE_SUBTITLES-$(call ENCDEC, MOVTEXT, MOV) += fate-sub-movtextenc
> > fate-sub-movtextenc: CMD = md5 -i $(SAMPLES)/sub/MovText_capability_tester.mp4 -map 0 -scodec mov_text -f mp4 -flags +bitexact -movflags frag_keyframe+empty_moov
> >
> > +FATE_SUBTITLES_ASS-$(call DEMDEC, MPL2, MPL2) += fate-sub-mpl2
> > +fate-sub-mpl2: CMD = md5 -i $(SAMPLES)/sub/MPL2_capability_tester.txt -f ass
> > +
> > FATE_SUBTITLES_ASS-$(call DEMDEC, REALTEXT, REALTEXT) += fate-sub-realtext
> > fate-sub-realtext: CMD = md5 -i $(SAMPLES)/sub/RealText_capability_tester.rt -f ass
> >
> > diff --git a/tests/ref/fate/sub-mpl2 b/tests/ref/fate/sub-mpl2
> > new file mode 100644
> > index 0000000..8835dd2
> > --- /dev/null
> > +++ b/tests/ref/fate/sub-mpl2
> > @@ -0,0 +1 @@
> > +3c2fb62002aec3af16d83135a0e3b0fc
>
> LGTM otherwise.
Will apply in a day or two, thanks.
--
Clément B.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20121229/d5bcf7c8/attachment.asc>
More information about the ffmpeg-devel
mailing list