Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Linshizhi
ffmpeg.wasm-core
Commits
29412821
Commit
29412821
authored
Jan 06, 2016
by
Clément Bœsch
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavc: allow subtitle text format to be ASS without timing
parent
805685ff
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
341 additions
and
236 deletions
+341
-236
APIchanges
doc/APIchanges
+17
-0
ass.c
libavcodec/ass.c
+18
-78
ass.h
libavcodec/ass.h
+14
-42
ass_split.c
libavcodec/ass_split.c
+49
-0
ass_split.h
libavcodec/ass_split.h
+15
-0
assdec.c
libavcodec/assdec.c
+12
-13
assenc.c
libavcodec/assenc.c
+2
-7
avcodec.h
libavcodec/avcodec.h
+4
-0
ccaption_dec.c
libavcodec/ccaption_dec.c
+11
-13
jacosubdec.c
libavcodec/jacosubdec.c
+4
-1
libzvbi-teletextdec.c
libavcodec/libzvbi-teletextdec.c
+13
-25
microdvddec.c
libavcodec/microdvddec.c
+4
-8
movtextdec.c
libavcodec/movtextdec.c
+10
-9
movtextenc.c
libavcodec/movtextenc.c
+11
-1
mpl2dec.c
libavcodec/mpl2dec.c
+4
-4
options_table.h
libavcodec/options_table.h
+3
-0
realtextdec.c
libavcodec/realtextdec.c
+4
-3
samidec.c
libavcodec/samidec.c
+10
-4
srtdec.c
libavcodec/srtdec.c
+7
-10
srtenc.c
libavcodec/srtenc.c
+13
-1
subviewerdec.c
libavcodec/subviewerdec.c
+4
-3
textdec.c
libavcodec/textdec.c
+14
-5
utils.c
libavcodec/utils.c
+74
-0
version.h
libavcodec/version.h
+2
-2
webvttdec.c
libavcodec/webvttdec.c
+5
-6
webvttenc.c
libavcodec/webvttenc.c
+13
-1
api-mjpeg-codec-param
tests/ref/fate/api-mjpeg-codec-param
+2
-0
api-png-codec-param
tests/ref/fate/api-png-codec-param
+2
-0
No files found.
doc/APIchanges
View file @
29412821
...
...
@@ -15,6 +15,23 @@ libavutil: 2015-08-28
API changes, most recent first:
2016-xx-xx - xxxxxxx - lavc 57.26.100 - avcodec.h
Add a "sub_text_format" subtitles decoding option allowing the values "ass"
(recommended) and "ass_with_timings" (not recommended, deprecated, default).
The default value for this option will change to "ass" at the next major
libavcodec version bump.
The current default is "ass_with_timings" for compatibility. This means that
all subtitles text decoders currently still output ASS with timings printed
as strings in the AVSubtitles.rects[N]->ass fields.
Setting "sub_text_format" to "ass" allows a better timing accuracy (ASS
timing is limited to a 1/100 time base, so this is relevant for any subtitles
format needing a bigger one), ease timing adjustments, and prevents the need
of removing the timing from the decoded string yourself. This form is also
known as "the Matroska form". The timing information (start time, duration)
can be found in the AVSubtitles fields.
2016-xx-xx - lavc 57.25.0 - avcodec.h
Add AVCodecContext.hw_frames_ctx.
...
...
libavcodec/ass.c
View file @
29412821
...
...
@@ -90,101 +90,41 @@ int ff_ass_subtitle_header_default(AVCodecContext *avctx)
ASS_DEFAULT_ALIGNMENT
);
}
static
void
insert_ts
(
AVBPrint
*
buf
,
int
ts
)
char
*
ff_ass_get_dialog
(
int
readorder
,
int
layer
,
const
char
*
style
,
const
char
*
speaker
,
const
char
*
text
)
{
if
(
ts
==
-
1
)
{
av_bprintf
(
buf
,
"9:59:59.99,"
);
}
else
{
int
h
,
m
,
s
;
h
=
ts
/
360000
;
ts
-=
360000
*
h
;
m
=
ts
/
6000
;
ts
-=
6000
*
m
;
s
=
ts
/
100
;
ts
-=
100
*
s
;
av_bprintf
(
buf
,
"%d:%02d:%02d.%02d,"
,
h
,
m
,
s
,
ts
);
}
}
int
ff_ass_bprint_dialog
(
AVBPrint
*
buf
,
const
char
*
dialog
,
int
ts_start
,
int
duration
,
int
raw
)
{
int
dlen
;
if
(
!
raw
||
raw
==
2
)
{
long
int
layer
=
0
;
if
(
raw
==
2
)
{
/* skip ReadOrder */
dialog
=
strchr
(
dialog
,
','
);
if
(
!
dialog
)
return
AVERROR_INVALIDDATA
;
dialog
++
;
/* extract Layer or Marked */
layer
=
strtol
(
dialog
,
(
char
**
)
&
dialog
,
10
);
if
(
*
dialog
!=
','
)
return
AVERROR_INVALIDDATA
;
dialog
++
;
}
av_bprintf
(
buf
,
"Dialogue: %ld,"
,
layer
);
insert_ts
(
buf
,
ts_start
);
insert_ts
(
buf
,
duration
==
-
1
?
-
1
:
ts_start
+
duration
);
if
(
raw
!=
2
)
av_bprintf
(
buf
,
"Default,,0,0,0,,"
);
}
dlen
=
strcspn
(
dialog
,
"
\n
"
);
dlen
+=
dialog
[
dlen
]
==
'\n'
;
av_bprintf
(
buf
,
"%.*s"
,
dlen
,
dialog
);
if
(
raw
==
2
)
av_bprintf
(
buf
,
"
\r\n
"
);
return
dlen
;
return
av_asprintf
(
"%d,%d,%s,%s,0,0,0,,%s"
,
readorder
,
layer
,
style
?
style
:
"Default"
,
speaker
?
speaker
:
""
,
text
);
}
int
ff_ass_add_rect
(
AVSubtitle
*
sub
,
const
char
*
dialog
,
int
ts_start
,
int
duration
,
int
raw
)
int
readorder
,
int
layer
,
const
char
*
style
,
const
char
*
speaker
)
{
AVBPrint
buf
;
int
ret
,
dlen
;
char
*
ass_str
;
AVSubtitleRect
**
rects
;
av_bprint_init
(
&
buf
,
0
,
AV_BPRINT_SIZE_UNLIMITED
);
if
((
ret
=
ff_ass_bprint_dialog
(
&
buf
,
dialog
,
ts_start
,
duration
,
raw
))
<
0
)
goto
err
;
dlen
=
ret
;
if
(
!
av_bprint_is_complete
(
&
buf
))
goto
errnomem
;
rects
=
av_realloc_array
(
sub
->
rects
,
(
sub
->
num_rects
+
1
),
sizeof
(
*
sub
->
rects
));
if
(
!
rects
)
goto
errnomem
;
return
AVERROR
(
ENOMEM
)
;
sub
->
rects
=
rects
;
sub
->
end_display_time
=
FFMAX
(
sub
->
end_display_time
,
10
*
duration
);
rects
[
sub
->
num_rects
]
=
av_mallocz
(
sizeof
(
*
rects
[
0
]));
if
(
!
rects
[
sub
->
num_rects
])
goto
errnomem
;
return
AVERROR
(
ENOMEM
)
;
rects
[
sub
->
num_rects
]
->
type
=
SUBTITLE_ASS
;
ret
=
av_bprint_finalize
(
&
buf
,
&
rects
[
sub
->
num_rects
]
->
ass
);
if
(
ret
<
0
)
goto
err
;
ass_str
=
ff_ass_get_dialog
(
readorder
,
layer
,
style
,
speaker
,
dialog
);
if
(
!
ass_str
)
return
AVERROR
(
ENOMEM
);
rects
[
sub
->
num_rects
]
->
ass
=
ass_str
;
sub
->
num_rects
++
;
return
dlen
;
errnomem:
ret
=
AVERROR
(
ENOMEM
);
err:
av_bprint_finalize
(
&
buf
,
NULL
);
return
ret
;
return
0
;
}
int
ff_ass_add_rect_bprint
(
AVSubtitle
*
sub
,
AVBPrint
*
buf
,
int
ts_start
,
int
duration
)
void
ff_ass_decoder_flush
(
AVCodecContext
*
avctx
)
{
av_bprintf
(
buf
,
"
\r\n
"
);
if
(
!
av_bprint_is_complete
(
buf
))
return
AVERROR
(
ENOMEM
);
return
ff_ass_add_rect
(
sub
,
buf
->
str
,
ts_start
,
duration
,
0
);
FFASSDecoderContext
*
s
=
avctx
->
priv_data
;
s
->
readorder
=
0
;
}
void
ff_ass_bprint_text_event
(
AVBPrint
*
buf
,
const
char
*
p
,
int
size
,
...
...
libavcodec/ass.h
View file @
29412821
...
...
@@ -43,6 +43,10 @@
#define ASS_DEFAULT_BORDERSTYLE 1
/** @} */
typedef
struct
FFASSDecoderContext
{
int
readorder
;
}
FFASSDecoderContext
;
/**
* Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS.
*
...
...
@@ -74,55 +78,23 @@ int ff_ass_subtitle_header(AVCodecContext *avctx,
int
ff_ass_subtitle_header_default
(
AVCodecContext
*
avctx
);
/**
* Add an ASS dialog line to an AVSubtitle as a new AVSubtitleRect.
*
* @param sub pointer to the AVSubtitle
* @param dialog ASS dialog to add to sub
* @param ts_start start timestamp for this dialog (in 1/100 second unit)
* @param duration duration for this dialog (in 1/100 second unit), can be -1
* to last until the end of the presentation
* @param raw when set to 2, it indicates that dialog contains an ASS
* dialog line as muxed in Matroska
* when set to 1, it indicates that dialog contains a whole SSA
* dialog line which should be copied as is.
* when set to 0, it indicates that dialog contains only the Text
* part of the ASS dialog line, the rest of the line
* will be generated.
* @return number of characters read from dialog. It can be less than the whole
* length of dialog, if dialog contains several lines of text.
* A negative value indicates an error.
* Craft an ASS dialog string.
*/
int
ff_ass_add_rect
(
AVSubtitle
*
sub
,
const
char
*
dialog
,
int
ts_start
,
int
duration
,
int
raw
);
char
*
ff_ass_get_dialog
(
int
readorder
,
int
layer
,
const
char
*
style
,
const
char
*
speaker
,
const
char
*
text
);
/**
* Same as ff_ass_add_rect, but taking an AVBPrint buffer instead of a
* string, and assuming raw=0.
* Add an ASS dialog to a subtitle.
*/
int
ff_ass_add_rect_bprint
(
AVSubtitle
*
sub
,
AVBPrint
*
buf
,
int
ts_start
,
int
duration
);
int
ff_ass_add_rect
(
AVSubtitle
*
sub
,
const
char
*
dialog
,
int
readorder
,
int
layer
,
const
char
*
style
,
const
char
*
speaker
);
/**
* Add an ASS dialog line to an AVBPrint buffer.
*
* @param buf pointer to an initialized AVBPrint buffer
* @param dialog ASS dialog to add to sub
* @param ts_start start timestamp for this dialog (in 1/100 second unit)
* @param duration duration for this dialog (in 1/100 second unit), can be -1
* to last until the end of the presentation
* @param raw when set to 2, it indicates that dialog contains an ASS
* dialog line as muxed in Matroska
* when set to 1, it indicates that dialog contains a whole SSA
* dialog line which should be copied as is.
* when set to 0, it indicates that dialog contains only the Text
* part of the ASS dialog line, the rest of the line
* will be generated.
* @return number of characters read from dialog. It can be less than the whole
* length of dialog, if dialog contains several lines of text.
* A negative value indicates an error.
* Helper to flush a text subtitles decoder making use of the
* FFASSDecoderContext.
*/
int
ff_ass_bprint_dialog
(
AVBPrint
*
buf
,
const
char
*
dialog
,
int
ts_start
,
int
duration
,
int
raw
);
void
ff_ass_decoder_flush
(
AVCodecContext
*
avctx
);
/**
* Escape a text subtitle using ASS syntax into an AVBPrint buffer.
...
...
libavcodec/ass_split.c
View file @
29412821
...
...
@@ -409,6 +409,55 @@ ASSDialog *ff_ass_split_dialog(ASSSplitContext *ctx, const char *buf,
return
dialog
;
}
void
ff_ass_free_dialog
(
ASSDialog
**
dialogp
)
{
ASSDialog
*
dialog
=
*
dialogp
;
if
(
!
dialog
)
return
;
av_freep
(
&
dialog
->
style
);
av_freep
(
&
dialog
->
name
);
av_freep
(
&
dialog
->
effect
);
av_freep
(
&
dialog
->
text
);
av_freep
(
dialogp
);
}
ASSDialog
*
ff_ass_split_dialog2
(
ASSSplitContext
*
ctx
,
const
char
*
buf
)
{
int
i
;
static
const
ASSFields
fields
[]
=
{
{
"ReadOrder"
,
ASS_INT
,
offsetof
(
ASSDialog
,
readorder
)},
{
"Layer"
,
ASS_INT
,
offsetof
(
ASSDialog
,
layer
)
},
{
"Style"
,
ASS_STR
,
offsetof
(
ASSDialog
,
style
)
},
{
"Name"
,
ASS_STR
,
offsetof
(
ASSDialog
,
name
)
},
{
"MarginL"
,
ASS_INT
,
offsetof
(
ASSDialog
,
margin_l
)
},
{
"MarginR"
,
ASS_INT
,
offsetof
(
ASSDialog
,
margin_r
)
},
{
"MarginV"
,
ASS_INT
,
offsetof
(
ASSDialog
,
margin_v
)
},
{
"Effect"
,
ASS_STR
,
offsetof
(
ASSDialog
,
effect
)
},
{
"Text"
,
ASS_STR
,
offsetof
(
ASSDialog
,
text
)
},
};
ASSDialog
*
dialog
=
av_mallocz
(
sizeof
(
*
dialog
));
if
(
!
dialog
)
return
NULL
;
for
(
i
=
0
;
i
<
FF_ARRAY_ELEMS
(
fields
);
i
++
)
{
size_t
len
;
const
int
last
=
i
==
FF_ARRAY_ELEMS
(
fields
)
-
1
;
const
ASSFieldType
type
=
fields
[
i
].
type
;
uint8_t
*
ptr
=
(
uint8_t
*
)
dialog
+
fields
[
i
].
offset
;
buf
=
skip_space
(
buf
);
len
=
last
?
strlen
(
buf
)
:
strcspn
(
buf
,
","
);
if
(
len
>=
INT_MAX
)
{
ff_ass_free_dialog
(
&
dialog
);
return
NULL
;
}
convert_func
[
type
](
ptr
,
buf
,
len
);
buf
+=
len
;
if
(
*
buf
)
buf
++
;
}
return
dialog
;
}
void
ff_ass_split_free
(
ASSSplitContext
*
ctx
)
{
if
(
ctx
)
{
...
...
libavcodec/ass_split.h
View file @
29412821
...
...
@@ -69,6 +69,7 @@ typedef struct {
* fields extracted from the [Events] section
*/
typedef
struct
{
int
readorder
;
int
layer
;
/**< higher numbered layers are drawn over lower numbered */
int
start
;
/**< start time of the dialog in centiseconds */
int
end
;
/**< end time of the dialog in centiseconds */
...
...
@@ -124,6 +125,20 @@ ASSSplitContext *ff_ass_split(const char *buf);
ASSDialog
*
ff_ass_split_dialog
(
ASSSplitContext
*
ctx
,
const
char
*
buf
,
int
cache
,
int
*
number
);
/**
* Free a dialogue obtained from ff_ass_split_dialog2().
*/
void
ff_ass_free_dialog
(
ASSDialog
**
dialogp
);
/**
* Split one ASS Dialogue line from a string buffer.
*
* @param ctx Context previously initialized by ff_ass_split().
* @param buf String containing the ASS "Dialogue" line.
* @return Pointer to the split ASSDialog. Must be freed with ff_ass_free_dialog()
*/
ASSDialog
*
ff_ass_split_dialog2
(
ASSSplitContext
*
ctx
,
const
char
*
buf
);
/**
* Free all the memory allocated for an ASSSplitContext.
*
...
...
libavcodec/assdec.c
View file @
29412821
...
...
@@ -40,24 +40,23 @@ static av_cold int ass_decode_init(AVCodecContext *avctx)
static
int
ass_decode_frame
(
AVCodecContext
*
avctx
,
void
*
data
,
int
*
got_sub_ptr
,
AVPacket
*
avpkt
)
{
int
ret
;
AVSubtitle
*
sub
=
data
;
const
char
*
ptr
=
avpkt
->
data
;
static
const
AVRational
ass_tb
=
{
1
,
100
};
const
int
ts_start
=
av_rescale_q
(
avpkt
->
pts
,
avctx
->
time_base
,
ass_tb
);
const
int
ts_duration
=
av_rescale_q
(
avpkt
->
duration
,
avctx
->
time_base
,
ass_tb
);
if
(
avpkt
->
size
<=
0
)
return
avpkt
->
size
;
ret
=
ff_ass_add_rect
(
sub
,
ptr
,
ts_start
,
ts_duration
,
2
);
if
(
ret
<
0
)
{
if
(
ret
==
AVERROR_INVALIDDATA
)
av_log
(
avctx
,
AV_LOG_ERROR
,
"Invalid ASS packet
\n
"
);
return
ret
;
}
*
got_sub_ptr
=
avpkt
->
size
>
0
;
sub
->
rects
=
av_malloc
(
sizeof
(
*
sub
->
rects
));
if
(
!
sub
->
rects
)
return
AVERROR
(
ENOMEM
);
sub
->
rects
[
0
]
=
av_mallocz
(
sizeof
(
*
sub
->
rects
[
0
]));
if
(
!
sub
->
rects
[
0
])
return
AVERROR
(
ENOMEM
);
sub
->
num_rects
=
1
;
sub
->
rects
[
0
]
->
type
=
SUBTITLE_ASS
;
sub
->
rects
[
0
]
->
ass
=
av_strdup
(
avpkt
->
data
);
if
(
!
sub
->
rects
[
0
]
->
ass
)
return
AVERROR
(
ENOMEM
);
*
got_sub_ptr
=
1
;
return
avpkt
->
size
;
}
...
...
libavcodec/assenc.c
View file @
29412821
...
...
@@ -60,13 +60,7 @@ static int ass_encode_frame(AVCodecContext *avctx,
return
-
1
;
}
if
(
strncmp
(
ass
,
"Dialogue: "
,
10
))
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"AVSubtitle rectangle ass
\"
%s
\"
"
" does not look like a SSA markup
\n
"
,
ass
);
return
AVERROR_INVALIDDATA
;
}
// TODO: reindent
if
(
!
strncmp
(
ass
,
"Dialogue: "
,
10
))
{
if
(
i
>
0
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"ASS encoder supports only one "
"ASS rectangle field.
\n
"
);
...
...
@@ -91,6 +85,7 @@ static int ass_encode_frame(AVCodecContext *avctx,
snprintf
(
ass_line
,
sizeof
(
ass_line
),
"%d,%ld,%s"
,
++
s
->
id
,
layer
,
p
);
ass_line
[
strcspn
(
ass_line
,
"
\r\n
"
)]
=
0
;
ass
=
ass_line
;
}
len
=
av_strlcpy
(
buf
+
total_len
,
ass
,
bufsize
-
total_len
);
...
...
libavcodec/avcodec.h
View file @
29412821
...
...
@@ -3285,6 +3285,10 @@ typedef struct AVCodecContext {
#define FF_SUB_CHARENC_MODE_AUTOMATIC 0 ///< libavcodec will select the mode itself
#define FF_SUB_CHARENC_MODE_PRE_DECODER 1 ///< the AVPacket data needs to be recoded to UTF-8 before being fed to the decoder, requires iconv
int
sub_text_format
;
#define FF_SUB_TEXT_FMT_ASS 0
#define FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS 1
/**
* Skip processing alpha if supported by codec.
* Note that if the format uses pre-multiplied alpha (common with VP6,
...
...
libavcodec/ccaption_dec.c
View file @
29412821
...
...
@@ -248,6 +248,7 @@ typedef struct CCaptionSubContext {
char
prev_cmd
[
2
];
/* buffer to store pkt data */
AVBufferRef
*
pktbuf
;
int
readorder
;
}
CCaptionSubContext
;
...
...
@@ -306,6 +307,7 @@ static void flush_decoder(AVCodecContext *avctx)
ctx
->
last_real_time
=
0
;
ctx
->
screen_touched
=
0
;
ctx
->
buffer_changed
=
0
;
ctx
->
readorder
=
0
;
av_bprint_clear
(
&
ctx
->
buffer
);
}
...
...
@@ -752,18 +754,16 @@ static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avp
if
(
*
ctx
->
buffer
.
str
||
ctx
->
real_time
)
{
int64_t
sub_pts
=
ctx
->
real_time
?
avpkt
->
pts
:
ctx
->
start_time
;
int
start_time
=
av_rescale_q
(
sub_pts
,
avctx
->
time_base
,
ass_tb
);
int
duration
=
-
1
;
if
(
!
ctx
->
real_time
)
{
int
end_time
=
av_rescale_q
(
ctx
->
end_time
,
avctx
->
time_base
,
ass_tb
);
duration
=
end_time
-
start_time
;
}
ff_dlog
(
ctx
,
"cdp writing data (%s)
\n
"
,
ctx
->
buffer
.
str
);
ret
=
ff_ass_add_rect
_bprint
(
sub
,
&
ctx
->
buffer
,
start_time
,
duration
);
ret
=
ff_ass_add_rect
(
sub
,
ctx
->
buffer
.
str
,
ctx
->
readorder
++
,
0
,
NULL
,
NULL
);
if
(
ret
<
0
)
return
ret
;
sub
->
pts
=
av_rescale_q
(
sub_pts
,
avctx
->
time_base
,
AV_TIME_BASE_Q
);
sub
->
pts
=
av_rescale_q
(
ctx
->
start_time
,
avctx
->
time_base
,
AV_TIME_BASE_Q
);
if
(
!
ctx
->
real_time
)
sub
->
end_display_time
=
av_rescale_q
(
ctx
->
end_time
-
ctx
->
start_time
,
avctx
->
time_base
,
av_make_q
(
1
,
1000
));
else
sub
->
end_display_time
=
-
1
;
ctx
->
buffer_changed
=
0
;
ctx
->
last_real_time
=
avpkt
->
pts
;
ctx
->
screen_touched
=
0
;
...
...
@@ -772,18 +772,16 @@ static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avp
if
(
ctx
->
real_time
&&
ctx
->
screen_touched
&&
avpkt
->
pts
>
ctx
->
last_real_time
+
av_rescale_q
(
20
,
ass_tb
,
avctx
->
time_base
))
{
int
start_time
;
ctx
->
last_real_time
=
avpkt
->
pts
;
ctx
->
screen_touched
=
0
;
capture_screen
(
ctx
);
ctx
->
buffer_changed
=
0
;
start_time
=
av_rescale_q
(
avpkt
->
pts
,
avctx
->
time_base
,
ass_tb
);
ret
=
ff_ass_add_rect_bprint
(
sub
,
&
ctx
->
buffer
,
start_time
,
-
1
);
ret
=
ff_ass_add_rect
(
sub
,
ctx
->
buffer
.
str
,
ctx
->
readorder
++
,
0
,
NULL
,
NULL
);
if
(
ret
<
0
)
return
ret
;
sub
->
pts
=
av_rescale_q
(
avpkt
->
pts
,
avctx
->
time_base
,
AV_TIME_BASE_Q
)
;
sub
->
end_display_time
=
-
1
;
}
*
got_sub
=
sub
->
num_rects
>
0
;
...
...
libavcodec/jacosubdec.c
View file @
29412821
...
...
@@ -167,6 +167,7 @@ static int jacosub_decode_frame(AVCodecContext *avctx,
int
ret
;
AVSubtitle
*
sub
=
data
;
const
char
*
ptr
=
avpkt
->
data
;
FFASSDecoderContext
*
s
=
avctx
->
priv_data
;
if
(
avpkt
->
size
<=
0
)
goto
end
;
...
...
@@ -181,7 +182,7 @@ static int jacosub_decode_frame(AVCodecContext *avctx,
av_bprint_init
(
&
buffer
,
JSS_MAX_LINESIZE
,
JSS_MAX_LINESIZE
);
jacosub_to_ass
(
avctx
,
&
buffer
,
ptr
);
ret
=
ff_ass_add_rect
_bprint
(
sub
,
&
buffer
,
avpkt
->
pts
,
avpkt
->
duration
);
ret
=
ff_ass_add_rect
(
sub
,
buffer
.
str
,
s
->
readorder
++
,
0
,
NULL
,
NULL
);
av_bprint_finalize
(
&
buffer
,
NULL
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -199,4 +200,6 @@ AVCodec ff_jacosub_decoder = {
.
id
=
AV_CODEC_ID_JACOSUB
,
.
init
=
ff_ass_subtitle_header_default
,
.
decode
=
jacosub_decode_frame
,
.
flush
=
ff_ass_decoder_flush
,
.
priv_data_size
=
sizeof
(
FFASSDecoderContext
),
};
libavcodec/libzvbi-teletextdec.c
View file @
29412821
...
...
@@ -74,6 +74,8 @@ typedef struct TeletextContext
vbi_export
*
ex
;
#endif
vbi_sliced
sliced
[
MAX_SLICES
];
int
readorder
;
}
TeletextContext
;
static
int
chop_spaces_utf8
(
const
unsigned
char
*
t
,
int
len
)
...
...
@@ -95,37 +97,21 @@ static void subtitle_rect_free(AVSubtitleRect **sub_rect)
av_freep
(
sub_rect
);
}
static
int
create_ass_text
(
TeletextContext
*
ctx
,
const
char
*
text
,
char
**
ass
)
static
char
*
create_ass_text
(
TeletextContext
*
ctx
,
const
char
*
text
)
{
int
ret
;
AVBPrint
buf
,
buf2
;
const
int
ts_start
=
av_rescale_q
(
ctx
->
pts
,
AV_TIME_BASE_Q
,
(
AVRational
){
1
,
100
});
const
int
ts_duration
=
av_rescale_q
(
ctx
->
sub_duration
,
(
AVRational
){
1
,
1000
},
(
AVRational
){
1
,
100
});
char
*
dialog
;
AVBPrint
buf
;
/* First we escape the plain text into buf. */
av_bprint_init
(
&
buf
,
0
,
AV_BPRINT_SIZE_UNLIMITED
);
ff_ass_bprint_text_event
(
&
buf
,
text
,
strlen
(
text
),
""
,
0
);
av_bprintf
(
&
buf
,
"
\r\n
"
);
if
(
!
av_bprint_is_complete
(
&
buf
))
{
av_bprint_finalize
(
&
buf
,
NULL
);
return
AVERROR
(
ENOMEM
)
;
return
NULL
;
}
/* Then we create the ass dialog line in buf2 from the escaped text in buf. */
av_bprint_init
(
&
buf2
,
0
,
AV_BPRINT_SIZE_UNLIMITED
);
ff_ass_bprint_dialog
(
&
buf2
,
buf
.
str
,
ts_start
,
ts_duration
,
0
);
dialog
=
ff_ass_get_dialog
(
ctx
->
readorder
++
,
0
,
NULL
,
NULL
,
buf
.
str
);
av_bprint_finalize
(
&
buf
,
NULL
);
if
(
!
av_bprint_is_complete
(
&
buf2
))
{
av_bprint_finalize
(
&
buf2
,
NULL
);
return
AVERROR
(
ENOMEM
);
}
if
((
ret
=
av_bprint_finalize
(
&
buf2
,
ass
))
<
0
)
return
ret
;
return
0
;
return
dialog
;
}
/* Draw a page as text */
...
...
@@ -181,11 +167,12 @@ static int gen_sub_text(TeletextContext *ctx, AVSubtitleRect *sub_rect, vbi_page
}
if
(
buf
.
len
)
{
int
ret
;
sub_rect
->
type
=
SUBTITLE_ASS
;
if
((
ret
=
create_ass_text
(
ctx
,
buf
.
str
,
&
sub_rect
->
ass
))
<
0
)
{
sub_rect
->
ass
=
create_ass_text
(
ctx
,
buf
.
str
);
if
(
!
sub_rect
->
ass
)
{
av_bprint_finalize
(
&
buf
,
NULL
);
return
ret
;
return
AVERROR
(
ENOMEM
)
;
}
av_log
(
ctx
,
AV_LOG_DEBUG
,
"subtext:%s:txetbus
\n
"
,
sub_rect
->
ass
);
}
else
{
...
...
@@ -541,6 +528,7 @@ static int teletext_close_decoder(AVCodecContext *avctx)
vbi_decoder_delete
(
ctx
->
vbi
);
ctx
->
vbi
=
NULL
;
ctx
->
pts
=
AV_NOPTS_VALUE
;
ctx
->
readorder
=
0
;
return
0
;
}
...
...
libavcodec/microdvddec.c
View file @
29412821
...
...
@@ -280,6 +280,7 @@ static int microdvd_decode_frame(AVCodecContext *avctx,
AVBPrint
new_line
;
char
*
line
=
avpkt
->
data
;
char
*
end
=
avpkt
->
data
+
avpkt
->
size
;
FFASSDecoderContext
*
s
=
avctx
->
priv_data
;
struct
microdvd_tag
tags
[
sizeof
(
MICRODVD_TAGS
)
-
1
]
=
{{
0
}};
if
(
avpkt
->
size
<=
0
)
...
...
@@ -308,14 +309,7 @@ static int microdvd_decode_frame(AVCodecContext *avctx,
}
}
if
(
new_line
.
len
)
{
int
ret
;
int64_t
start
=
avpkt
->
pts
;
int64_t
duration
=
avpkt
->
duration
;
int
ts_start
=
av_rescale_q
(
start
,
avctx
->
time_base
,
(
AVRational
){
1
,
100
});
int
ts_duration
=
duration
!=
-
1
?
av_rescale_q
(
duration
,
avctx
->
time_base
,
(
AVRational
){
1
,
100
})
:
-
1
;
ret
=
ff_ass_add_rect_bprint
(
sub
,
&
new_line
,
ts_start
,
ts_duration
);
int
ret
=
ff_ass_add_rect
(
sub
,
new_line
.
str
,
s
->
readorder
++
,
0
,
NULL
,
NULL
);
av_bprint_finalize
(
&
new_line
,
NULL
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -381,4 +375,6 @@ AVCodec ff_microdvd_decoder = {
.
id
=
AV_CODEC_ID_MICRODVD
,
.
init
=
microdvd_init
,
.
decode
=
microdvd_decode_frame
,
.
flush
=
ff_ass_decoder_flush
,
.
priv_data_size
=
sizeof
(
FFASSDecoderContext
),
};
libavcodec/movtextdec.c
View file @
29412821
...
...
@@ -99,6 +99,7 @@ typedef struct {
uint64_t
tracksize
;
int
size_var
;
int
count_s
,
count_f
;
int
readorder
;
}
MovTextContext
;
typedef
struct
{
...
...
@@ -424,7 +425,7 @@ static int mov_text_decode_frame(AVCodecContext *avctx,
{
AVSubtitle
*
sub
=
data
;
MovTextContext
*
m
=
avctx
->
priv_data
;
int
ret
,
ts_start
,
ts_end
;
int
ret
;
AVBPrint
buf
;
char
*
ptr
=
avpkt
->
data
;
char
*
end
;
...
...
@@ -454,13 +455,6 @@ static int mov_text_decode_frame(AVCodecContext *avctx,
end
=
ptr
+
FFMIN
(
2
+
text_length
,
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
});
tsmb_size
=
0
;
m
->
tracksize
=
2
+
text_length
;
m
->
style_entries
=
0
;
...
...
@@ -506,7 +500,7 @@ static int mov_text_decode_frame(AVCodecContext *avctx,
}
else
text_to_ass
(
&
buf
,
ptr
,
end
,
m
);
ret
=
ff_ass_add_rect
_bprint
(
sub
,
&
buf
,
ts_start
,
ts_end
-
ts_start
);
ret
=
ff_ass_add_rect
(
sub
,
buf
.
str
,
m
->
readorder
++
,
0
,
NULL
,
NULL
);
av_bprint_finalize
(
&
buf
,
NULL
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -521,6 +515,12 @@ static int mov_text_decode_close(AVCodecContext *avctx)
return
0
;
}
static
void
mov_text_flush
(
AVCodecContext
*
avctx
)
{
MovTextContext
*
m
=
avctx
->
priv_data
;
m
->
readorder
=
0
;
}
AVCodec
ff_movtext_decoder
=
{
.
name
=
"mov_text"
,
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"3GPP Timed Text subtitle"
),
...
...
@@ -530,4 +530,5 @@ AVCodec ff_movtext_decoder = {
.
init
=
mov_text_init
,
.
decode
=
mov_text_decode_frame
,
.
close
=
mov_text_decode_close
,
.
flush
=
mov_text_flush
,
};
libavcodec/movtextenc.c
View file @
29412821
...
...
@@ -332,16 +332,26 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf,
s
->
box_flags
=
0
;
s
->
style_entries
=
0
;
for
(
i
=
0
;
i
<
sub
->
num_rects
;
i
++
)
{
const
char
*
ass
=
sub
->
rects
[
i
]
->
ass
;
if
(
sub
->
rects
[
i
]
->
type
!=
SUBTITLE_ASS
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Only SUBTITLE_ASS type supported.
\n
"
);
return
AVERROR
(
ENOSYS
);
}
dialog
=
ff_ass_split_dialog
(
s
->
ass_ctx
,
sub
->
rects
[
i
]
->
ass
,
0
,
&
num
);
if
(
!
strncmp
(
ass
,
"Dialogue: "
,
10
))
{
dialog
=
ff_ass_split_dialog
(
s
->
ass_ctx
,
ass
,
0
,
&
num
);
// TODO reindent
for
(;
dialog
&&
num
--
;
dialog
++
)
{
ff_ass_split_override_codes
(
&
mov_text_callbacks
,
s
,
dialog
->
text
);
}
}
else
{
dialog
=
ff_ass_split_dialog2
(
s
->
ass_ctx
,
ass
);
if
(
!
dialog
)
return
AVERROR
(
ENOMEM
);
ff_ass_split_override_codes
(
&
mov_text_callbacks
,
s
,
dialog
->
text
);
ff_ass_free_dialog
(
&
dialog
);
}
for
(
j
=
0
;
j
<
box_count
;
j
++
)
{
box_types
[
j
].
encode
(
s
,
box_types
[
j
].
type
);
...
...
libavcodec/mpl2dec.c
View file @
29412821
...
...
@@ -69,13 +69,11 @@ static int mpl2_decode_frame(AVCodecContext *avctx, void *data,
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
?
av_rescale_q
(
avpkt
->
duration
,
avctx
->
time_base
,
(
AVRational
){
1
,
100
})
:
-
1
;
FFASSDecoderContext
*
s
=
avctx
->
priv_data
;
av_bprint_init
(
&
buf
,
0
,
AV_BPRINT_SIZE_UNLIMITED
);
if
(
ptr
&&
avpkt
->
size
>
0
&&
*
ptr
&&
!
mpl2_event_to_ass
(
&
buf
,
ptr
))
ret
=
ff_ass_add_rect
_bprint
(
sub
,
&
buf
,
ts_start
,
ts_duration
);
ret
=
ff_ass_add_rect
(
sub
,
buf
.
str
,
s
->
readorder
++
,
0
,
NULL
,
NULL
);
av_bprint_finalize
(
&
buf
,
NULL
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -90,4 +88,6 @@ AVCodec ff_mpl2_decoder = {
.
id
=
AV_CODEC_ID_MPL2
,
.
decode
=
mpl2_decode_frame
,
.
init
=
ff_ass_subtitle_header_default
,
.
flush
=
ff_ass_decoder_flush
,
.
priv_data_size
=
sizeof
(
FFASSDecoderContext
),
};
libavcodec/options_table.h
View file @
29412821
...
...
@@ -519,6 +519,9 @@ static const AVOption avcodec_options[] = {
{
"do_nothing"
,
NULL
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
FF_SUB_CHARENC_MODE_DO_NOTHING
},
INT_MIN
,
INT_MAX
,
S
|
D
,
"sub_charenc_mode"
},
{
"auto"
,
NULL
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
FF_SUB_CHARENC_MODE_AUTOMATIC
},
INT_MIN
,
INT_MAX
,
S
|
D
,
"sub_charenc_mode"
},
{
"pre_decoder"
,
NULL
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
FF_SUB_CHARENC_MODE_PRE_DECODER
},
INT_MIN
,
INT_MAX
,
S
|
D
,
"sub_charenc_mode"
},
{
"sub_text_format"
,
"set decoded text subtitle format"
,
OFFSET
(
sub_text_format
),
AV_OPT_TYPE_INT
,
{.
i64
=
FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS
},
0
,
1
,
S
|
D
,
"sub_text_format"
},
{
"ass"
,
NULL
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
FF_SUB_TEXT_FMT_ASS
},
INT_MIN
,
INT_MAX
,
S
|
D
,
"sub_text_format"
},
{
"ass_with_timings"
,
NULL
,
0
,
AV_OPT_TYPE_CONST
,
{.
i64
=
FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS
},
INT_MIN
,
INT_MAX
,
S
|
D
,
"sub_text_format"
},
{
"refcounted_frames"
,
NULL
,
OFFSET
(
refcounted_frames
),
AV_OPT_TYPE_BOOL
,
{.
i64
=
0
},
0
,
1
,
A
|
V
|
D
},
#if FF_API_SIDEDATA_ONLY_PKT
{
"side_data_only_packets"
,
NULL
,
OFFSET
(
side_data_only_packets
),
AV_OPT_TYPE_BOOL
,
{
.
i64
=
1
},
0
,
1
,
A
|
V
|
E
},
...
...
libavcodec/realtextdec.c
View file @
29412821
...
...
@@ -61,13 +61,12 @@ static int realtext_decode_frame(AVCodecContext *avctx,
int
ret
=
0
;
AVSubtitle
*
sub
=
data
;
const
char
*
ptr
=
avpkt
->
data
;
FFASSDecoderContext
*
s
=
avctx
->
priv_data
;
AVBPrint
buf
;
av_bprint_init
(
&
buf
,
0
,
4096
);
// note: no need to rescale pts & duration since they are in the same
// timebase as ASS (1/100)
if
(
ptr
&&
avpkt
->
size
>
0
&&
!
rt_event_to_ass
(
&
buf
,
ptr
))
ret
=
ff_ass_add_rect
_bprint
(
sub
,
&
buf
,
avpkt
->
pts
,
avpkt
->
duration
);
ret
=
ff_ass_add_rect
(
sub
,
buf
.
str
,
s
->
readorder
++
,
0
,
NULL
,
NULL
);
av_bprint_finalize
(
&
buf
,
NULL
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -82,4 +81,6 @@ AVCodec ff_realtext_decoder = {
.
id
=
AV_CODEC_ID_REALTEXT
,
.
decode
=
realtext_decode_frame
,
.
init
=
ff_ass_subtitle_header_default
,
.
flush
=
ff_ass_decoder_flush
,
.
priv_data_size
=
sizeof
(
FFASSDecoderContext
),
};
libavcodec/samidec.c
View file @
29412821
...
...
@@ -35,6 +35,7 @@ typedef struct {
AVBPrint
encoded_source
;
AVBPrint
encoded_content
;
AVBPrint
full
;
int
readorder
;
}
SAMIContext
;
static
int
sami_paragraph_to_ass
(
AVCodecContext
*
avctx
,
const
char
*
src
)
...
...
@@ -131,10 +132,8 @@ static int sami_decode_frame(AVCodecContext *avctx,
SAMIContext
*
sami
=
avctx
->
priv_data
;
if
(
ptr
&&
avpkt
->
size
>
0
&&
!
sami_paragraph_to_ass
(
avctx
,
ptr
))
{
int
ts_start
=
av_rescale_q
(
avpkt
->
pts
,
avctx
->
time_base
,
(
AVRational
){
1
,
100
});
int
ts_duration
=
avpkt
->
duration
!=
-
1
?
av_rescale_q
(
avpkt
->
duration
,
avctx
->
time_base
,
(
AVRational
){
1
,
100
})
:
-
1
;
int
ret
=
ff_ass_add_rect_bprint
(
sub
,
&
sami
->
full
,
ts_start
,
ts_duration
);
// TODO: pass escaped sami->encoded_source.str as source
int
ret
=
ff_ass_add_rect
(
sub
,
sami
->
full
.
str
,
sami
->
readorder
++
,
0
,
NULL
,
NULL
);
if
(
ret
<
0
)
return
ret
;
}
...
...
@@ -164,6 +163,12 @@ static av_cold int sami_close(AVCodecContext *avctx)
return
0
;
}
static
void
sami_flush
(
AVCodecContext
*
avctx
)
{
SAMIContext
*
sami
=
avctx
->
priv_data
;
sami
->
readorder
=
0
;
}
AVCodec
ff_sami_decoder
=
{
.
name
=
"sami"
,
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"SAMI subtitle"
),
...
...
@@ -173,4 +178,5 @@ AVCodec ff_sami_decoder = {
.
init
=
sami_init
,
.
close
=
sami_close
,
.
decode
=
sami_decode_frame
,
.
flush
=
sami_flush
,
};
libavcodec/srtdec.c
View file @
29412821
...
...
@@ -57,9 +57,10 @@ static int srt_decode_frame(AVCodecContext *avctx,
{
AVSubtitle
*
sub
=
data
;
AVBPrint
buffer
;
int
ts_start
,
ts_end
,
x1
=
-
1
,
y1
=
-
1
,
x2
=
-
1
,
y2
=
-
1
;
int
x1
=
-
1
,
y1
=
-
1
,
x2
=
-
1
,
y2
=
-
1
;
int
size
,
ret
;
const
uint8_t
*
p
=
av_packet_get_side_data
(
avpkt
,
AV_PKT_DATA_SUBTITLE_POSITION
,
&
size
);
FFASSDecoderContext
*
s
=
avctx
->
priv_data
;
if
(
p
&&
size
==
16
)
{
x1
=
AV_RL32
(
p
);
...
...
@@ -73,16 +74,8 @@ static int srt_decode_frame(AVCodecContext *avctx,
av_bprint_init
(
&
buffer
,
0
,
AV_BPRINT_SIZE_UNLIMITED
);
// Do final divide-by-10 outside rescale to force rounding down.
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
});
srt_to_ass
(
avctx
,
&
buffer
,
avpkt
->
data
,
x1
,
y1
,
x2
,
y2
);
ret
=
ff_ass_add_rect
_bprint
(
sub
,
&
buffer
,
ts_start
,
ts_end
-
ts_start
);
ret
=
ff_ass_add_rect
(
sub
,
buffer
.
str
,
s
->
readorder
++
,
0
,
NULL
,
NULL
);
av_bprint_finalize
(
&
buffer
,
NULL
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -100,6 +93,8 @@ AVCodec ff_srt_decoder = {
.
id
=
AV_CODEC_ID_SUBRIP
,
.
init
=
ff_ass_subtitle_header_default
,
.
decode
=
srt_decode_frame
,
.
flush
=
ff_ass_decoder_flush
,
.
priv_data_size
=
sizeof
(
FFASSDecoderContext
),
};
#endif
...
...
@@ -111,5 +106,7 @@ AVCodec ff_subrip_decoder = {
.
id
=
AV_CODEC_ID_SUBRIP
,
.
init
=
ff_ass_subtitle_header_default
,
.
decode
=
srt_decode_frame
,
.
flush
=
ff_ass_decoder_flush
,
.
priv_data_size
=
sizeof
(
FFASSDecoderContext
),
};
#endif
libavcodec/srtenc.c
View file @
29412821
...
...
@@ -237,18 +237,30 @@ static int encode_frame(AVCodecContext *avctx,
av_bprint_clear
(
&
s
->
buffer
);
for
(
i
=
0
;
i
<
sub
->
num_rects
;
i
++
)
{
const
char
*
ass
=
sub
->
rects
[
i
]
->
ass
;
if
(
sub
->
rects
[
i
]
->
type
!=
SUBTITLE_ASS
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Only SUBTITLE_ASS type supported.
\n
"
);
return
AVERROR
(
ENOSYS
);
}
dialog
=
ff_ass_split_dialog
(
s
->
ass_ctx
,
sub
->
rects
[
i
]
->
ass
,
0
,
&
num
);
if
(
!
strncmp
(
ass
,
"Dialogue: "
,
10
))
{
dialog
=
ff_ass_split_dialog
(
s
->
ass_ctx
,
ass
,
0
,
&
num
);
// TODO reindent
for
(;
dialog
&&
num
--
;
dialog
++
)
{
s
->
alignment_applied
=
0
;
srt_style_apply
(
s
,
dialog
->
style
);
ff_ass_split_override_codes
(
cb
,
s
,
dialog
->
text
);
}
}
else
{
dialog
=
ff_ass_split_dialog2
(
s
->
ass_ctx
,
ass
);
if
(
!
dialog
)
return
AVERROR
(
ENOMEM
);
s
->
alignment_applied
=
0
;
srt_style_apply
(
s
,
dialog
->
style
);
ff_ass_split_override_codes
(
cb
,
s
,
dialog
->
text
);
ff_ass_free_dialog
(
&
dialog
);
}
}
if
(
!
av_bprint_is_complete
(
&
s
->
buffer
))
...
...
libavcodec/subviewerdec.c
View file @
29412821
...
...
@@ -52,13 +52,12 @@ static int subviewer_decode_frame(AVCodecContext *avctx,
int
ret
=
0
;
AVSubtitle
*
sub
=
data
;
const
char
*
ptr
=
avpkt
->
data
;
FFASSDecoderContext
*
s
=
avctx
->
priv_data
;
AVBPrint
buf
;
av_bprint_init
(
&
buf
,
0
,
AV_BPRINT_SIZE_UNLIMITED
);
// note: no need to rescale pts & duration since they are in the same
// timebase as ASS (1/100)
if
(
ptr
&&
avpkt
->
size
>
0
&&
!
subviewer_event_to_ass
(
&
buf
,
ptr
))
ret
=
ff_ass_add_rect
_bprint
(
sub
,
&
buf
,
avpkt
->
pts
,
avpkt
->
duration
);
ret
=
ff_ass_add_rect
(
sub
,
buf
.
str
,
s
->
readorder
++
,
0
,
NULL
,
NULL
);
av_bprint_finalize
(
&
buf
,
NULL
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -73,4 +72,6 @@ AVCodec ff_subviewer_decoder = {
.
id
=
AV_CODEC_ID_SUBVIEWER
,
.
decode
=
subviewer_decode_frame
,
.
init
=
ff_ass_subtitle_header_default
,
.
flush
=
ff_ass_decoder_flush
,
.
priv_data_size
=
sizeof
(
FFASSDecoderContext
),
};
libavcodec/textdec.c
View file @
29412821
...
...
@@ -32,6 +32,7 @@ typedef struct {
AVClass
*
class
;
const
char
*
linebreaks
;
int
keep_ass_markup
;
int
readorder
;
}
TextContext
;
#define OFFSET(x) offsetof(TextContext, x)
...
...
@@ -48,15 +49,12 @@ static int text_decode_frame(AVCodecContext *avctx, void *data,
AVBPrint
buf
;
AVSubtitle
*
sub
=
data
;
const
char
*
ptr
=
avpkt
->
data
;
const
TextContext
*
text
=
avctx
->
priv_data
;
const
int
ts_start
=
av_rescale_q
(
avpkt
->
pts
,
avctx
->
time_base
,
(
AVRational
){
1
,
100
});
const
int
ts_duration
=
avpkt
->
duration
!=
-
1
?
av_rescale_q
(
avpkt
->
duration
,
avctx
->
time_base
,
(
AVRational
){
1
,
100
})
:
-
1
;
TextContext
*
text
=
avctx
->
priv_data
;
av_bprint_init
(
&
buf
,
0
,
AV_BPRINT_SIZE_UNLIMITED
);
if
(
ptr
&&
avpkt
->
size
>
0
&&
*
ptr
)
{
ff_ass_bprint_text_event
(
&
buf
,
ptr
,
avpkt
->
size
,
text
->
linebreaks
,
text
->
keep_ass_markup
);
ret
=
ff_ass_add_rect
_bprint
(
sub
,
&
buf
,
ts_start
,
ts_duration
);
ret
=
ff_ass_add_rect
(
sub
,
buf
.
str
,
text
->
readorder
++
,
0
,
NULL
,
NULL
);
}
av_bprint_finalize
(
&
buf
,
NULL
);
if
(
ret
<
0
)
...
...
@@ -65,6 +63,12 @@ static int text_decode_frame(AVCodecContext *avctx, void *data,
return
avpkt
->
size
;
}
static
void
text_flush
(
AVCodecContext
*
avctx
)
{
TextContext
*
text
=
avctx
->
priv_data
;
text
->
readorder
=
0
;
}
#define DECLARE_CLASS(decname) static const AVClass decname ## _decoder_class = { \
.class_name = #decname " decoder", \
.item_name = av_default_item_name, \
...
...
@@ -85,6 +89,7 @@ AVCodec ff_text_decoder = {
.
decode
=
text_decode_frame
,
.
init
=
ff_ass_subtitle_header_default
,
.
priv_class
=
&
text_decoder_class
,
.
flush
=
text_flush
,
};
#endif
...
...
@@ -110,6 +115,7 @@ AVCodec ff_vplayer_decoder = {
.
decode
=
text_decode_frame
,
.
init
=
linebreak_init
,
.
priv_class
=
&
vplayer_decoder_class
,
.
flush
=
text_flush
,
};
#endif
...
...
@@ -126,6 +132,7 @@ AVCodec ff_stl_decoder = {
.
decode
=
text_decode_frame
,
.
init
=
linebreak_init
,
.
priv_class
=
&
stl_decoder_class
,
.
flush
=
text_flush
,
};
#endif
...
...
@@ -142,6 +149,7 @@ AVCodec ff_pjs_decoder = {
.
decode
=
text_decode_frame
,
.
init
=
linebreak_init
,
.
priv_class
=
&
pjs_decoder_class
,
.
flush
=
text_flush
,
};
#endif
...
...
@@ -158,6 +166,7 @@ AVCodec ff_subviewer1_decoder = {
.
decode
=
text_decode_frame
,
.
init
=
linebreak_init
,
.
priv_class
=
&
subviewer1_decoder_class
,
.
flush
=
text_flush
,
};
#endif
...
...
libavcodec/utils.c
View file @
29412821
...
...
@@ -2426,6 +2426,76 @@ static int utf8_check(const uint8_t *str)
return
1
;
}
static
void
insert_ts
(
AVBPrint
*
buf
,
int
ts
)
{
if
(
ts
==
-
1
)
{
av_bprintf
(
buf
,
"9:59:59.99,"
);
}
else
{
int
h
,
m
,
s
;
h
=
ts
/
360000
;
ts
-=
360000
*
h
;
m
=
ts
/
6000
;
ts
-=
6000
*
m
;
s
=
ts
/
100
;
ts
-=
100
*
s
;
av_bprintf
(
buf
,
"%d:%02d:%02d.%02d,"
,
h
,
m
,
s
,
ts
);
}
}
static
int
convert_sub_to_old_ass_form
(
AVSubtitle
*
sub
,
const
AVPacket
*
pkt
,
AVRational
tb
)
{
int
i
;
AVBPrint
buf
;
av_bprint_init
(
&
buf
,
0
,
AV_BPRINT_SIZE_UNLIMITED
);
for
(
i
=
0
;
i
<
sub
->
num_rects
;
i
++
)
{
char
*
final_dialog
;
const
char
*
dialog
;
AVSubtitleRect
*
rect
=
sub
->
rects
[
i
];
int
ts_start
,
ts_duration
=
-
1
;
long
int
layer
;
if
(
rect
->
type
!=
SUBTITLE_ASS
||
!
strncmp
(
rect
->
ass
,
"Dialogue "
,
10
))
continue
;
av_bprint_clear
(
&
buf
);
/* skip ReadOrder */
dialog
=
strchr
(
rect
->
ass
,
','
);
if
(
!
dialog
)
continue
;
dialog
++
;
/* extract Layer or Marked */
layer
=
strtol
(
dialog
,
(
char
**
)
&
dialog
,
10
);
if
(
*
dialog
!=
','
)
continue
;
dialog
++
;
/* rescale timing to ASS time base (ms) */
ts_start
=
av_rescale_q
(
pkt
->
pts
,
tb
,
av_make_q
(
1
,
100
));
if
(
pkt
->
duration
!=
-
1
)
ts_duration
=
av_rescale_q
(
pkt
->
duration
,
tb
,
av_make_q
(
1
,
100
));
sub
->
end_display_time
=
FFMAX
(
sub
->
end_display_time
,
10
*
ts_duration
);
/* construct ASS (standalone file form with timestamps) string */
av_bprintf
(
&
buf
,
"Dialogue: %ld,"
,
layer
);
insert_ts
(
&
buf
,
ts_start
);
insert_ts
(
&
buf
,
ts_duration
==
-
1
?
-
1
:
ts_start
+
ts_duration
);
av_bprintf
(
&
buf
,
"%s
\r\n
"
,
dialog
);
final_dialog
=
av_strdup
(
buf
.
str
);
if
(
!
av_bprint_is_complete
(
&
buf
)
||
!
final_dialog
)
{
av_bprint_finalize
(
&
buf
,
NULL
);
return
AVERROR
(
ENOMEM
);
}
av_freep
(
&
rect
->
ass
);
rect
->
ass
=
final_dialog
;
}
av_bprint_finalize
(
&
buf
,
NULL
);
return
0
;
}
int
avcodec_decode_subtitle2
(
AVCodecContext
*
avctx
,
AVSubtitle
*
sub
,
int
*
got_sub_ptr
,
AVPacket
*
avpkt
)
...
...
@@ -2476,6 +2546,10 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
av_assert1
((
ret
>=
0
)
>=
!!*
got_sub_ptr
&&
!!*
got_sub_ptr
>=
!!
sub
->
num_rects
);
if
(
avctx
->
sub_text_format
==
FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS
&&
*
got_sub_ptr
&&
sub
->
num_rects
)
ret
=
convert_sub_to_old_ass_form
(
sub
,
avpkt
,
avctx
->
time_base
);
if
(
sub
->
num_rects
&&
!
sub
->
end_display_time
&&
avpkt
->
duration
&&
avctx
->
pkt_timebase
.
num
)
{
AVRational
ms
=
{
1
,
1000
};
...
...
libavcodec/version.h
View file @
29412821
...
...
@@ -28,8 +28,8 @@
#include "libavutil/version.h"
#define LIBAVCODEC_VERSION_MAJOR 57
#define LIBAVCODEC_VERSION_MINOR 2
5
#define LIBAVCODEC_VERSION_MICRO 10
1
#define LIBAVCODEC_VERSION_MINOR 2
6
#define LIBAVCODEC_VERSION_MICRO 10
0
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \
...
...
libavcodec/webvttdec.c
View file @
29412821
...
...
@@ -85,15 +85,12 @@ static int webvtt_decode_frame(AVCodecContext *avctx,
int
ret
=
0
;
AVSubtitle
*
sub
=
data
;
const
char
*
ptr
=
avpkt
->
data
;
FFASSDecoderContext
*
s
=
avctx
->
priv_data
;
AVBPrint
buf
;
av_bprint_init
(
&
buf
,
0
,
AV_BPRINT_SIZE_UNLIMITED
);
if
(
ptr
&&
avpkt
->
size
>
0
&&
!
webvtt_event_to_ass
(
&
buf
,
ptr
))
{
int
ts_start
=
av_rescale_q
(
avpkt
->
pts
,
avctx
->
time_base
,
(
AVRational
){
1
,
100
});
int
ts_duration
=
avpkt
->
duration
!=
-
1
?
av_rescale_q
(
avpkt
->
duration
,
avctx
->
time_base
,
(
AVRational
){
1
,
100
})
:
-
1
;
ret
=
ff_ass_add_rect_bprint
(
sub
,
&
buf
,
ts_start
,
ts_duration
);
}
if
(
ptr
&&
avpkt
->
size
>
0
&&
!
webvtt_event_to_ass
(
&
buf
,
ptr
))
ret
=
ff_ass_add_rect
(
sub
,
buf
.
str
,
s
->
readorder
++
,
0
,
NULL
,
NULL
);
av_bprint_finalize
(
&
buf
,
NULL
);
if
(
ret
<
0
)
return
ret
;
...
...
@@ -108,4 +105,6 @@ AVCodec ff_webvtt_decoder = {
.
id
=
AV_CODEC_ID_WEBVTT
,
.
decode
=
webvtt_decode_frame
,
.
init
=
ff_ass_subtitle_header_default
,
.
flush
=
ff_ass_decoder_flush
,
.
priv_data_size
=
sizeof
(
FFASSDecoderContext
),
};
libavcodec/webvttenc.c
View file @
29412821
...
...
@@ -164,16 +164,28 @@ static int webvtt_encode_frame(AVCodecContext *avctx,
av_bprint_clear
(
&
s
->
buffer
);
for
(
i
=
0
;
i
<
sub
->
num_rects
;
i
++
)
{
const
char
*
ass
=
sub
->
rects
[
i
]
->
ass
;
if
(
sub
->
rects
[
i
]
->
type
!=
SUBTITLE_ASS
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Only SUBTITLE_ASS type supported.
\n
"
);
return
AVERROR
(
ENOSYS
);
}
dialog
=
ff_ass_split_dialog
(
s
->
ass_ctx
,
sub
->
rects
[
i
]
->
ass
,
0
,
&
num
);
if
(
!
strncmp
(
ass
,
"Dialogue: "
,
10
))
{
dialog
=
ff_ass_split_dialog
(
s
->
ass_ctx
,
ass
,
0
,
&
num
);
// TODO reindent
for
(;
dialog
&&
num
--
;
dialog
++
)
{
webvtt_style_apply
(
s
,
dialog
->
style
);
ff_ass_split_override_codes
(
&
webvtt_callbacks
,
s
,
dialog
->
text
);
}
}
else
{
dialog
=
ff_ass_split_dialog2
(
s
->
ass_ctx
,
ass
);
if
(
!
dialog
)
return
AVERROR
(
ENOMEM
);
webvtt_style_apply
(
s
,
dialog
->
style
);
ff_ass_split_override_codes
(
&
webvtt_callbacks
,
s
,
dialog
->
text
);
ff_ass_free_dialog
(
&
dialog
);
}
}
if
(
!
av_bprint_is_complete
(
&
s
->
buffer
))
...
...
tests/ref/fate/api-mjpeg-codec-param
View file @
29412821
...
...
@@ -145,6 +145,7 @@ stream=0, decode=0
pkt_timebase=1/25
sub_charenc=
sub_charenc_mode=0x00000000
sub_text_format=1
refcounted_frames=false
side_data_only_packets=true
skip_alpha=false
...
...
@@ -300,6 +301,7 @@ stream=0, decode=1
pkt_timebase=1/25
sub_charenc=
sub_charenc_mode=0x00000000
sub_text_format=1
refcounted_frames=false
side_data_only_packets=true
skip_alpha=false
...
...
tests/ref/fate/api-png-codec-param
View file @
29412821
...
...
@@ -145,6 +145,7 @@ stream=0, decode=0
pkt_timebase=1/25
sub_charenc=
sub_charenc_mode=0x00000000
sub_text_format=1
refcounted_frames=false
side_data_only_packets=true
skip_alpha=false
...
...
@@ -300,6 +301,7 @@ stream=0, decode=1
pkt_timebase=1/25
sub_charenc=
sub_charenc_mode=0x00000000
sub_text_format=1
refcounted_frames=false
side_data_only_packets=true
skip_alpha=false
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment