[FFmpeg-devel] [PATCH] Pass "forced" flag to dvdsubenc

Oliver Fromme oliver at fromme.com
Mon May 19 17:48:02 CEST 2014


Anshul wrote:
 > On May 19, 2014 1:58:21 AM IST, Anshul <anshul.ffmpeg at gmail.com> wrote:
 > > On May 18, 2014 6:59:28 PM IST, Oliver Fromme <oliver at fromme.com>
 > > wrote:
 > > > Hi,
 > > > 
 > > > I hope this is the right place to submit a patch.
 > > > Please let me know if there's something wrong with it.
 > > > The patch was made against a recent snapshot downloaded
 > > > from ffmpeg.org on 2014-05-16.  I'm not familiar with
 > > > git at all (my version-control background is rather cvs,
 > > > subversion and perforce), so I just used "diff -u".
 > > > The patch is fairly trivial and small, so it shouldn't
 > > > be an issue.
 > > > 
 > > > The problem is that I'm working with a lot with subtitle
 > > > tracks that are either completely forced or that contain
 > > > some captions that are forced (and some that are not).
 > > > At the moment, ffmpeg and libavcodec don't support this
 > > > very well.  I'll try to improve this in small steps.
 > > > 
 > > > My first observation when looking at the source code was
 > > > that there is already a flag:  AV_SUBTITLE_FLAG_FORCED.
 > > > However, at the moment this flag is only set by pgssubdec
 > > > dvdsubdec, but it is never used anywhere.  That means,
 > > > if subtitles are read from a PGS or VOBSUB track and
 > > > then later written to the destination file, the "forced"
 > > > flag is lost.
 > > > 
 > > > The patch presented below causes the flag to be used when
 > > > writing a VOBSUB track ("dvdsub" in ffmpeg parlance), so
 > > > the flag is preserved.  I've tested the patch with various
 > > > VOBSUB tracks successfully.
 > > > 
 > > > By the way, a good way for testing VOBSUB subtitles files
 > > > (i.e. pairs of *.idx and *.sub files) is the BDSup2Sub
 > > > utility.  It's written in Java and supports both a GUI
 > > > and a pure command-line interface (I only use the latter).
 > > > The good thing about it is that it has a very strict
 > > > parser.  If anything is wrong with the VOBSUB input, it
 > > > prints appropriate warnings and error messages.  It also
 > > > prints the number of captions marked as forced, and allows
 > > > to extract them separately.  ffmpeg doesn't support this
 > > > yet, but I'll try to implement something like that when
 > > > I have some spare time.  Yes, I know, there already is the
 > > > -forced_subs_only option, but it's specific to the PGS
 > > > decoder, and it doesn't work anyway because of a bug.
 > > > 
 > > > Best regards
 > > >   Oliver
 > > > 
 > > > PS:  Here's the patch to use the "forced" flag in dvdsubenc:
 > > > 
 > > > --- libavcodec/dvdsubenc.c.orig	2014-04-25 19:20:06.000000000 +0200
 > > > +++ libavcodec/dvdsubenc.c	2014-05-16 23:35:29.000000000 +0200
 > > > @@ -259,6 +259,7 @@
 > > >     AVSubtitleRect vrect;
 > > >     uint8_t *vrect_data = NULL;
 > > >     int x2, y2;
 > > > +    int forced = 0;
 > > > 
 > > >     if (rects == 0 || h->rects == NULL)
 > > >         return AVERROR(EINVAL);
 > > > @@ -267,6 +268,12 @@
 > > >             av_log(avctx, AV_LOG_ERROR, "Bitmap subtitle
 > > required\n");
 > > >             return AVERROR(EINVAL);
 > > >         }
 > > > +    /* Mark this subtitle forced if any of the rectangles is forced.
 > > > */
 > > > +    for (i = 0; i < rects; i++)
 > > > +        if ((h->rects[i]->flags & AV_SUBTITLE_FLAG_FORCED) != 0) {
 > > > +            forced = 1;
 > > > +            break;
 > > > +        }
 > > >     vrect = *h->rects[0];
 > > > 
 > > >     if (rects > 1) {
 > > > @@ -371,7 +378,7 @@
 > > >     bytestream_put_be16(&q, offset1);
 > > >     bytestream_put_be16(&q, offset2);
 > > > 
 > > > -    *q++ = 0x01; // start command
 > > > +    *q++ = forced ? 0x00 : 0x01; // start command
 > > >     *q++ = 0xff; // terminating command
 > > > 
 > > >     // send stop display command last
 > > > _______________________________________________
 > > > ffmpeg-devel mailing list
 > > > ffmpeg-devel at ffmpeg.org
 > > > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 > > 
 > > Hi
 > > 
 > > In dvb subtitle rfc,  I dont find anything related to force flag.
 > > If you are following some documentation then can u please point
 > > section.
 > > 
 > > It would be better if you also share the input, where forced flag is
 > > lost.
 > > 
 > > -Anshul
 > 
 > Sry I was looking in wrong rfc its dvd not dvb.
 > 
 > I am really wondering how start command set to 0 is forcing to
 > display that rectangle, logicaly it should not show any display till
 > its set to 1. But cant say about anything surely till I read some
 > rfc.

There is no RFC.  The DVD specifications are managed by the
DVD Forum.  In order to get a copy, you have to sign an NDA
and pay $5000.

Most of the open source DVD software was implemented based on
reverse-engineering.  As far as DVD subtitles are concerned,
there's a pretty good document here:

http://dvd.sourceforge.net/spu_notes

It is quite terse and incomplete, but it contains most of the
information required to handle SPUs (sub-picture units).

Some background:  On DVDs, sub-pictures are used for two
things:  For menu texts and for subtitle texts.  The only
technical difference is that "normal" subtitles are only
displayed if the user has enabled them, while menus are
always displayed, no matter if subtitles are enabled or not.
This is why they are also used for "forced" subtitles.
So, basically, a menu sub-picture and a forced subtitle
are the same thing.

A menu text (or forced subtitle) is indicated by the control
type 0x00, while a normal subtitle uses control type 0x01.
A single sub-picture never uses 0x00 and 0x01 at the same
time; it doesn't make sense.

Here's a real-life example directly from a DVD that crossed
my way.  I've uploaded a subtitle (within an mkv container)
to upload.ffmpeg.org, the file name is subt-forced-test.mkv.
This subtitle track contains 991 captions (i.e. 991 subtitle
frames), of which 2 are "forced", the remaining 989 are normal
(not forced).  So this track can be used to test handling of
the "forced" flag in subtitles.  The two forced captions are
these (from the *.idx file):

timestamp: 00:19:07:000, filepos: 00006d000
timestamp: 01:34:57:000, filepos: 00027f800

When these subtitles are read by dvdsubdec.c and then later written
to a new file by dvdsubenc.c, the "forced" flag is lost, i.e. all
991 captions are normal in the new file.

With the patch presented in my previous message (see above)
the "forced" flag is passed through, so it is preserved in the
new file.  A very simple way to test it would be this command:

$ ffmpeg -i subt-forced-test.mkv -c:s dvdsub new.mkv

Unfortunately, ffmpeg has no way to display how many captions
are forced.  There are other tools that can do it.  One way is
to extract the VOBSUB track from the MKV container (e.g. using
the mkvextract tool from the "mkvtoolnix" package for unix)
and then run BDSub2Sup (a Java tool), like this:

$ mkvextract tracks new.mkv 0:test.idx
$ BDSup2Sub test.idx test2.idx /forced | grep -i detected
Detected 2 forced captions.

Let's get a little more technical and have a look at the bits
and bytes of the first forced frame ...  :-)

As you can see in the *.idx file (see above), the offset of that
sub-picture in the *.sub file is 0x6d000.  The *.sub file is
just an excerpt from the MPEG2 stream, i.e. it comes directly
from the DVD's VOB files.  Starting at that offset, you can
manually decode the PS and PES packets (assuming that you are
familiar with MPEG2; this is not DVD-specific).  After the
data packet that contains the actual graphics lines of the
sub-picture, the control packet starts at offset 0x6dfe5 in
the *.sub file.  There you will find the following bytes:

control packet:
  0f c6                --> = x1 (offset of end sequence)
control sequences:
  03 00 f0             --> 0x03: color index (0, 0, 15, 0)
  04 0f f0             --> 0x04: alpha index (0, 15, 15, 0)
  05 0b 32 1a 1a 61 e8 --> 0x05: x = 179 to 538, y = 422 to 488
  06 00 04 07 de       --> 0x06: graphics offsets (1st: 0x004, 2nd: 0x07de)
  00                   --> 0x00: menu caption (forced)
  ff                   --> 0xff: end marker
end sequence:
  00 68                --> duration 4.16s (104 frames at 25 fps)
  0f c6                --> = x1 (same as above)
  02                   --> 0x02: stop display

Note that there is *no* 0x01 control byte, only 0x00.  So this
is exactly what my patch does for forced subtitle frames.

If you have further questions, please let me know.

Best regards
   Oliver


-- 
``We are all but compressed light'' (Albert Einstein)


More information about the ffmpeg-devel mailing list