Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
F
ffmpeg
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
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
ffmpeg
Commits
774ceee1
Commit
774ceee1
authored
Jul 12, 2015
by
Niklesh
Committed by
Philip Langdale
Jul 12, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
movtextdec.c: Add support for highlight and hilightcolor box
Signed-off-by:
Niklesh
<
niklesh.lalwani@iitb.ac.in
>
parent
a3b721d1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
172 additions
and
80 deletions
+172
-80
movtextdec.c
libavcodec/movtextdec.c
+172
-80
No files found.
libavcodec/movtextdec.c
View file @
774ceee1
...
...
@@ -31,37 +31,165 @@
#define STYLE_FLAG_ITALIC (1<<1)
#define STYLE_FLAG_UNDERLINE (1<<2)
#define STYL_BOX (1<<0)
#define HLIT_BOX (1<<1)
#define HCLR_BOX (1<<2)
typedef
struct
{
uint16_t
style_start
;
uint16_t
style_end
;
uint8_t
style_flag
;
}
StyleBox
;
typedef
struct
{
uint16_t
hlit_start
;
uint16_t
hlit_end
;
}
HighlightBox
;
typedef
struct
{
uint8_t
hlit_color
[
4
];
}
HilightcolorBox
;
typedef
struct
{
StyleBox
**
s
;
StyleBox
*
s_temp
;
HighlightBox
h
;
HilightcolorBox
c
;
uint8_t
box_flags
;
uint16_t
style_entries
;
uint64_t
tracksize
;
int
size_var
;
int
count_s
;
}
MovTextContext
;
typedef
struct
{
uint32_t
type
;
size_t
base_size
;
int
(
*
decode
)(
const
uint8_t
*
tsmb
,
MovTextContext
*
m
,
AVPacket
*
avpkt
);
}
Box
;
static
void
mov_text_cleanup
(
MovTextContext
*
m
)
{
int
i
;
if
(
m
->
box_flags
&
STYL_BOX
)
{
for
(
i
=
0
;
i
<
m
->
count_s
;
i
++
)
{
av_freep
(
&
m
->
s
[
i
]);
}
av_freep
(
&
m
->
s
);
}
}
static
int
decode_hlit
(
const
uint8_t
*
tsmb
,
MovTextContext
*
m
,
AVPacket
*
avpkt
)
{
m
->
box_flags
|=
HLIT_BOX
;
m
->
h
.
hlit_start
=
AV_RB16
(
tsmb
);
tsmb
+=
2
;
m
->
h
.
hlit_end
=
AV_RB16
(
tsmb
);
tsmb
+=
2
;
return
0
;
}
static
int
decode_hclr
(
const
uint8_t
*
tsmb
,
MovTextContext
*
m
,
AVPacket
*
avpkt
)
{
m
->
box_flags
|=
HCLR_BOX
;
memcpy
(
m
->
c
.
hlit_color
,
tsmb
,
4
);
tsmb
+=
4
;
return
0
;
}
static
int
decode_styl
(
const
uint8_t
*
tsmb
,
MovTextContext
*
m
,
AVPacket
*
avpkt
)
{
int
i
;
m
->
style_entries
=
AV_RB16
(
tsmb
);
tsmb
+=
2
;
// A single style record is of length 12 bytes.
if
(
m
->
tracksize
+
m
->
size_var
+
2
+
m
->
style_entries
*
12
>
avpkt
->
size
)
return
-
1
;
m
->
box_flags
|=
STYL_BOX
;
for
(
i
=
0
;
i
<
m
->
style_entries
;
i
++
)
{
m
->
s_temp
=
av_malloc
(
sizeof
(
*
m
->
s_temp
));
if
(
!
m
->
s_temp
)
{
mov_text_cleanup
(
m
);
return
AVERROR
(
ENOMEM
);
}
m
->
s_temp
->
style_start
=
AV_RB16
(
tsmb
);
tsmb
+=
2
;
m
->
s_temp
->
style_end
=
AV_RB16
(
tsmb
);
tsmb
+=
2
;
// fontID = AV_RB16(tsmb);
tsmb
+=
2
;
m
->
s_temp
->
style_flag
=
AV_RB8
(
tsmb
);
av_dynarray_add
(
&
m
->
s
,
&
m
->
count_s
,
m
->
s_temp
);
if
(
!
m
->
s
)
{
mov_text_cleanup
(
m
);
return
AVERROR
(
ENOMEM
);
}
// fontsize = AV_RB8(tsmb);
tsmb
+=
2
;
// text-color-rgba
tsmb
+=
4
;
}
return
0
;
}
static
const
Box
box_types
[]
=
{
{
MKBETAG
(
's'
,
't'
,
'y'
,
'l'
),
2
,
decode_styl
},
{
MKBETAG
(
'h'
,
'l'
,
'i'
,
't'
),
4
,
decode_hlit
},
{
MKBETAG
(
'h'
,
'c'
,
'l'
,
'r'
),
4
,
decode_hclr
}
};
const
static
size_t
box_count
=
FF_ARRAY_ELEMS
(
box_types
);
static
int
text_to_ass
(
AVBPrint
*
buf
,
const
char
*
text
,
const
char
*
text_end
,
StyleBox
**
s
,
int
style_entries
)
MovTextContext
*
m
)
{
int
i
=
0
;
int
text_pos
=
0
;
while
(
text
<
text_end
)
{
for
(
i
=
0
;
i
<
style_entries
;
i
++
)
{
if
(
s
[
i
]
->
style_flag
&&
text_pos
==
s
[
i
]
->
style_end
)
{
if
(
s
[
i
]
->
style_flag
&
STYLE_FLAG_BOLD
)
av_bprintf
(
buf
,
"{
\\
b0}"
);
if
(
s
[
i
]
->
style_flag
&
STYLE_FLAG_ITALIC
)
av_bprintf
(
buf
,
"{
\\
i0}"
);
if
(
s
[
i
]
->
style_flag
&
STYLE_FLAG_UNDERLINE
)
av_bprintf
(
buf
,
"{
\\
u0}"
);
if
(
m
->
box_flags
&
STYL_BOX
)
{
for
(
i
=
0
;
i
<
m
->
style_entries
;
i
++
)
{
if
(
m
->
s
[
i
]
->
style_flag
&&
text_pos
==
m
->
s
[
i
]
->
style_end
)
{
if
(
m
->
s
[
i
]
->
style_flag
&
STYLE_FLAG_BOLD
)
av_bprintf
(
buf
,
"{
\\
b0}"
);
if
(
m
->
s
[
i
]
->
style_flag
&
STYLE_FLAG_ITALIC
)
av_bprintf
(
buf
,
"{
\\
i0}"
);
if
(
m
->
s
[
i
]
->
style_flag
&
STYLE_FLAG_UNDERLINE
)
av_bprintf
(
buf
,
"{
\\
u0}"
);
}
}
for
(
i
=
0
;
i
<
m
->
style_entries
;
i
++
)
{
if
(
m
->
s
[
i
]
->
style_flag
&&
text_pos
==
m
->
s
[
i
]
->
style_start
)
{
if
(
m
->
s
[
i
]
->
style_flag
&
STYLE_FLAG_BOLD
)
av_bprintf
(
buf
,
"{
\\
b1}"
);
if
(
m
->
s
[
i
]
->
style_flag
&
STYLE_FLAG_ITALIC
)
av_bprintf
(
buf
,
"{
\\
i1}"
);
if
(
m
->
s
[
i
]
->
style_flag
&
STYLE_FLAG_UNDERLINE
)
av_bprintf
(
buf
,
"{
\\
u1}"
);
}
}
}
for
(
i
=
0
;
i
<
style_entries
;
i
++
)
{
if
(
s
[
i
]
->
style_flag
&&
text_pos
==
s
[
i
]
->
style_start
)
{
if
(
s
[
i
]
->
style_flag
&
STYLE_FLAG_BOLD
)
av_bprintf
(
buf
,
"{
\\
b1}"
);
if
(
s
[
i
]
->
style_flag
&
STYLE_FLAG_ITALIC
)
av_bprintf
(
buf
,
"{
\\
i1}"
);
if
(
s
[
i
]
->
style_flag
&
STYLE_FLAG_UNDERLINE
)
av_bprintf
(
buf
,
"{
\\
u1}"
);
if
(
m
->
box_flags
&
HLIT_BOX
)
{
if
(
text_pos
==
m
->
h
.
hlit_start
)
{
/* If hclr box is present, set the secondary color to the color
* specified. Otherwise, set primary color to white and secondary
* color to black. These colors will come from TextSampleModifier
* boxes in future and inverse video technique for highlight will
* be implemented.
*/
if
(
m
->
box_flags
&
HCLR_BOX
)
{
av_bprintf
(
buf
,
"{
\\
2c&H%02x%02x%02x&}"
,
m
->
c
.
hlit_color
[
2
],
m
->
c
.
hlit_color
[
1
],
m
->
c
.
hlit_color
[
0
]);
}
else
{
av_bprintf
(
buf
,
"{
\\
1c&H000000&}{
\\
2c&HFFFFFF}"
);
}
}
if
(
text_pos
==
m
->
h
.
hlit_end
)
{
if
(
m
->
box_flags
&
HCLR_BOX
)
{
av_bprintf
(
buf
,
"{
\\
2c&H000000}"
);
}
else
{
av_bprintf
(
buf
,
"{
\\
1c&HFFFFFF&}{
\\
2c&H000000}"
);
}
}
}
...
...
@@ -96,17 +224,14 @@ static int mov_text_decode_frame(AVCodecContext *avctx,
void
*
data
,
int
*
got_sub_ptr
,
AVPacket
*
avpkt
)
{
AVSubtitle
*
sub
=
data
;
MovTextContext
*
m
=
avctx
->
priv_data
;
int
ret
,
ts_start
,
ts_end
;
AVBPrint
buf
;
char
*
ptr
=
avpkt
->
data
;
char
*
end
;
//char *ptr_temp;
int
text_length
,
tsmb_type
,
style_entries
;
uint64_t
tsmb_size
,
tracksize
;
StyleBox
**
s
=
{
0
,
};
StyleBox
*
s_temp
;
int
text_length
,
tsmb_type
,
ret_tsmb
;
uint64_t
tsmb_size
;
const
uint8_t
*
tsmb
;
int
count
,
i
,
size_var
;
if
(
!
ptr
||
avpkt
->
size
<
2
)
return
AVERROR_INVALIDDATA
;
...
...
@@ -138,73 +263,49 @@ static int mov_text_decode_frame(AVCodecContext *avctx,
(
AVRational
){
1
,
100
});
tsmb_size
=
0
;
tracksize
=
2
+
text_length
;
m
->
tracksize
=
2
+
text_length
;
m
->
style_entries
=
0
;
m
->
box_flags
=
0
;
m
->
count_s
=
0
;
// Note that the spec recommends lines be no longer than 2048 characters.
av_bprint_init
(
&
buf
,
0
,
AV_BPRINT_SIZE_UNLIMITED
);
if
(
text_length
+
2
!=
avpkt
->
size
)
{
while
(
tracksize
+
8
<=
avpkt
->
size
)
{
while
(
m
->
tracksize
+
8
<=
avpkt
->
size
)
{
// A box is a minimum of 8 bytes.
tsmb
=
ptr
+
tracksize
-
2
;
tsmb
=
ptr
+
m
->
tracksize
-
2
;
tsmb_size
=
AV_RB32
(
tsmb
);
tsmb
+=
4
;
tsmb_type
=
AV_RB32
(
tsmb
);
tsmb
+=
4
;
if
(
tsmb_size
==
1
)
{
if
(
tracksize
+
16
>
avpkt
->
size
)
if
(
m
->
tracksize
+
16
>
avpkt
->
size
)
break
;
tsmb_size
=
AV_RB64
(
tsmb
);
tsmb
+=
8
;
size_var
=
18
;
m
->
size_var
=
16
;
}
else
size_var
=
10
;
//size_var is equal to
10 or 18
depending on the size of box
m
->
size_var
=
8
;
//size_var is equal to
8 or 16
depending on the size of box
if
(
tracksize
+
tsmb_size
>
avpkt
->
size
)
if
(
m
->
tracksize
+
tsmb_size
>
avpkt
->
size
)
break
;
if
(
tsmb_type
==
MKBETAG
(
's'
,
't'
,
'y'
,
'l'
))
{
if
(
tracksize
+
size_var
>
avpkt
->
size
)
break
;
style_entries
=
AV_RB16
(
tsmb
);
tsmb
+=
2
;
// A single style record is of length 12 bytes.
if
(
tracksize
+
size_var
+
style_entries
*
12
>
avpkt
->
size
)
break
;
count
=
0
;
for
(
i
=
0
;
i
<
style_entries
;
i
++
)
{
s_temp
=
av_malloc
(
sizeof
(
*
s_temp
));
if
(
!
s_temp
)
goto
error
;
s_temp
->
style_start
=
AV_RB16
(
tsmb
);
tsmb
+=
2
;
s_temp
->
style_end
=
AV_RB16
(
tsmb
);
tsmb
+=
2
;
// fontID = AV_RB16(tsmb);
tsmb
+=
2
;
s_temp
->
style_flag
=
AV_RB8
(
tsmb
);
av_dynarray_add
(
&
s
,
&
count
,
s_temp
);
if
(
!
s
)
goto
error
;
//fontsize=AV_RB8(tsmb);
tsmb
+=
2
;
// text-color-rgba
tsmb
+=
4
;
}
text_to_ass
(
&
buf
,
ptr
,
end
,
s
,
style_entries
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
av_freep
(
&
s
[
i
]);
for
(
size_t
i
=
0
;
i
<
box_count
;
i
++
)
{
if
(
tsmb_type
==
box_types
[
i
].
type
)
{
if
(
m
->
tracksize
+
m
->
size_var
+
box_types
[
i
].
base_size
>
avpkt
->
size
)
break
;
ret_tsmb
=
box_types
[
i
].
decode
(
tsmb
,
m
,
avpkt
);
if
(
ret_tsmb
==
-
1
)
break
;
}
av_freep
(
&
s
);
}
tracksize
=
tracksize
+
tsmb_size
;
m
->
tracksize
=
m
->
tracksize
+
tsmb_size
;
}
text_to_ass
(
&
buf
,
ptr
,
end
,
m
);
mov_text_cleanup
(
m
);
}
else
text_to_ass
(
&
buf
,
ptr
,
end
,
NULL
,
0
);
text_to_ass
(
&
buf
,
ptr
,
end
,
m
);
ret
=
ff_ass_add_rect_bprint
(
sub
,
&
buf
,
ts_start
,
ts_end
-
ts_start
);
av_bprint_finalize
(
&
buf
,
NULL
);
...
...
@@ -212,16 +313,6 @@ static int mov_text_decode_frame(AVCodecContext *avctx,
return
ret
;
*
got_sub_ptr
=
sub
->
num_rects
>
0
;
return
avpkt
->
size
;
error:
for
(
i
=
0
;
i
<
count
;
i
++
)
{
av_freep
(
&
s
[
i
]);
}
av_freep
(
&
s
);
if
(
s_temp
)
av_freep
(
&
s_temp
);
av_bprint_finalize
(
&
buf
,
NULL
);
return
AVERROR
(
ENOMEM
);
}
AVCodec
ff_movtext_decoder
=
{
...
...
@@ -229,6 +320,7 @@ AVCodec ff_movtext_decoder = {
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"3GPP Timed Text subtitle"
),
.
type
=
AVMEDIA_TYPE_SUBTITLE
,
.
id
=
AV_CODEC_ID_MOV_TEXT
,
.
priv_data_size
=
sizeof
(
MovTextContext
),
.
init
=
mov_text_init
,
.
decode
=
mov_text_decode_frame
,
};
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