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
e0260e25
Commit
e0260e25
authored
Nov 23, 2012
by
Clément Bœsch
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavf/assdec: rewrite using the demux subtitles API.
parent
bad4e112
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
75 additions
and
120 deletions
+75
-120
assdec.c
libavformat/assdec.c
+75
-120
No files found.
libavformat/assdec.c
View file @
e0260e25
...
@@ -19,17 +19,13 @@
...
@@ -19,17 +19,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
*/
#include "libavutil/mathematics.h"
#include "avformat.h"
#include "avformat.h"
#include "internal.h"
#include "internal.h"
#include "subtitles.h"
#
define MAX_LINESIZE 2000
#
include "libavutil/bprint.h"
typedef
struct
ASSContext
{
typedef
struct
ASSContext
{
uint8_t
*
event_buffer
;
FFDemuxSubtitlesQueue
q
;
uint8_t
**
event
;
unsigned
int
event_count
;
unsigned
int
event_index
;
}
ASSContext
;
}
ASSContext
;
static
int
probe
(
AVProbeData
*
p
)
static
int
probe
(
AVProbeData
*
p
)
...
@@ -46,43 +42,49 @@ static int probe(AVProbeData *p)
...
@@ -46,43 +42,49 @@ static int probe(AVProbeData *p)
static
int
read_close
(
AVFormatContext
*
s
)
static
int
read_close
(
AVFormatContext
*
s
)
{
{
ASSContext
*
ass
=
s
->
priv_data
;
ASSContext
*
ass
=
s
->
priv_data
;
ff_subtitles_queue_clean
(
&
ass
->
q
);
av_freep
(
&
ass
->
event_buffer
);
av_freep
(
&
ass
->
event
);
return
0
;
return
0
;
}
}
static
int
64_t
get_pts
(
const
uint8_t
*
p
)
static
int
read_ts
(
const
uint8_t
*
p
,
int64_t
*
start
,
int
*
duration
)
{
{
int
hour
,
min
,
sec
,
hsec
;
int64_t
end
;
int
hh1
,
mm1
,
ss1
,
ms1
;
if
(
sscanf
(
p
,
"%*[^,],%d:%d:%d%*c%d"
,
&
hour
,
&
min
,
&
sec
,
&
hsec
)
!=
4
)
int
hh2
,
mm2
,
ss2
,
ms2
;
return
AV_NOPTS_VALUE
;
if
(
sscanf
(
p
,
"%*[^,],%d:%d:%d%*c%d,%d:%d:%d%*c%d"
,
av_dlog
(
NULL
,
"%d %d %d %d [%s]
\n
"
,
hour
,
min
,
sec
,
hsec
,
p
);
&
hh1
,
&
mm1
,
&
ss1
,
&
ms1
,
&
hh2
,
&
mm2
,
&
ss2
,
&
ms2
)
==
8
)
{
min
+=
60
*
hour
;
end
=
(
hh2
*
3600LL
+
mm2
*
60LL
+
ss2
)
*
100LL
+
ms2
;
sec
+=
60
*
min
;
*
start
=
(
hh1
*
3600LL
+
mm1
*
60LL
+
ss1
)
*
100LL
+
ms1
;
*
duration
=
end
-
*
start
;
return
sec
*
100
+
hsec
;
return
0
;
}
return
-
1
;
}
}
static
int
event_cmp
(
const
void
*
_a
,
const
void
*
_
b
)
static
int
64_t
get_line
(
AVBPrint
*
buf
,
AVIOContext
*
p
b
)
{
{
const
uint8_t
*
const
*
a
=
_a
,
*
const
*
b
=
_b
;
int64_t
pos
=
avio_tell
(
pb
);
return
get_pts
(
*
a
)
-
get_pts
(
*
b
);
av_bprint_clear
(
buf
);
for
(;;)
{
char
c
=
avio_r8
(
pb
);
if
(
!
c
)
break
;
av_bprint_chars
(
buf
,
c
,
1
);
if
(
c
==
'\n'
)
break
;
}
return
pos
;
}
}
static
int
read_header
(
AVFormatContext
*
s
)
static
int
read_header
(
AVFormatContext
*
s
)
{
{
int
i
,
len
,
header_remaining
;
ASSContext
*
ass
=
s
->
priv_data
;
ASSContext
*
ass
=
s
->
priv_data
;
AVIOContext
*
pb
=
s
->
pb
;
AVBPrint
header
,
line
;
int
header_remaining
,
res
=
0
;
AVStream
*
st
;
AVStream
*
st
;
int
allocated
[
2
]
=
{
0
};
uint8_t
*
p
,
**
dst
[
2
]
=
{
0
};
int
pos
[
2
]
=
{
0
};
st
=
avformat_new_stream
(
s
,
NULL
);
st
=
avformat_new_stream
(
s
,
NULL
);
if
(
!
st
)
if
(
!
st
)
...
@@ -92,116 +94,69 @@ static int read_header(AVFormatContext *s)
...
@@ -92,116 +94,69 @@ static int read_header(AVFormatContext *s)
st
->
codec
->
codec_id
=
AV_CODEC_ID_SSA
;
st
->
codec
->
codec_id
=
AV_CODEC_ID_SSA
;
header_remaining
=
INT_MAX
;
header_remaining
=
INT_MAX
;
dst
[
0
]
=
&
st
->
codec
->
extradata
;
dst
[
1
]
=
&
ass
->
event_buffer
;
while
(
!
url_feof
(
pb
)){
uint8_t
line
[
MAX_LINESIZE
];
len
=
ff_get_line
(
pb
,
line
,
sizeof
(
line
));
av_bprint_init
(
&
header
,
0
,
AV_BPRINT_SIZE_UNLIMITED
);
av_bprint_init
(
&
line
,
0
,
AV_BPRINT_SIZE_UNLIMITED
);
for
(;;)
{
int64_t
pos
=
get_line
(
&
line
,
s
->
pb
);
if
(
!
memcmp
(
line
,
"[Events]"
,
8
))
if
(
!
line
.
str
[
0
])
// EOF
break
;
if
(
!
memcmp
(
line
.
str
,
"[Events]"
,
8
))
header_remaining
=
2
;
header_remaining
=
2
;
else
if
(
line
[
0
]
==
'['
)
else
if
(
line
.
str
[
0
]
==
'['
)
header_remaining
=
INT_MAX
;
header_remaining
=
INT_MAX
;
i
=
header_remaining
==
0
;
if
(
header_remaining
)
{
av_bprintf
(
&
header
,
"%s"
,
line
.
str
);
header_remaining
--
;
}
else
{
int64_t
ts_start
=
AV_NOPTS_VALUE
;
int
duration
=
-
1
;
AVPacket
*
sub
;
if
(
i
&&
get_pts
(
line
)
==
AV_NOPTS_VALUE
)
if
(
read_ts
(
line
.
str
,
&
ts_start
,
&
duration
)
<
0
)
continue
;
continue
;
sub
=
ff_subtitles_queue_insert
(
&
ass
->
q
,
line
.
str
,
line
.
len
,
0
);
p
=
av_fast_realloc
(
*
(
dst
[
i
]),
&
allocated
[
i
],
pos
[
i
]
+
MAX_LINESIZE
);
if
(
!
sub
)
{
if
(
!
p
)
res
=
AVERROR
(
ENOMEM
);
goto
fail
;
goto
end
;
*
(
dst
[
i
])
=
p
;
}
memcpy
(
p
+
pos
[
i
],
line
,
len
+
1
);
sub
->
pos
=
pos
;
pos
[
i
]
+=
len
;
sub
->
pts
=
ts_start
;
if
(
i
)
ass
->
event_count
++
;
sub
->
duration
=
duration
;
else
header_remaining
--
;
}
}
st
->
codec
->
extradata_size
=
pos
[
0
];
if
(
ass
->
event_count
>=
UINT_MAX
/
sizeof
(
*
ass
->
event
))
goto
fail
;
ass
->
event
=
av_malloc
(
ass
->
event_count
*
sizeof
(
*
ass
->
event
));
p
=
ass
->
event_buffer
;
for
(
i
=
0
;
i
<
ass
->
event_count
;
i
++
){
ass
->
event
[
i
]
=
p
;
while
(
*
p
&&
*
p
!=
'\n'
)
p
++
;
p
++
;
}
}
qsort
(
ass
->
event
,
ass
->
event_count
,
sizeof
(
*
ass
->
event
),
event_cmp
);
av_bprint_finalize
(
&
line
,
NULL
);
return
0
;
av_bprint_finalize
(
&
header
,
(
char
**
)
&
st
->
codec
->
extradata
);
if
(
!
st
->
codec
->
extradata
)
{
res
=
AVERROR
(
ENOMEM
);
goto
end
;
}
st
->
codec
->
extradata_size
=
header
.
len
+
1
;
fail:
ff_subtitles_queue_finalize
(
&
ass
->
q
);
read_close
(
s
);
return
-
1
;
end:
return
res
;
}
}
static
int
read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
static
int
read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
{
{
ASSContext
*
ass
=
s
->
priv_data
;
ASSContext
*
ass
=
s
->
priv_data
;
uint8_t
*
p
,
*
end
;
return
ff_subtitles_queue_read_packet
(
&
ass
->
q
,
pkt
);
if
(
ass
->
event_index
>=
ass
->
event_count
)
return
AVERROR_EOF
;
p
=
ass
->
event
[
ass
->
event_index
];
end
=
strchr
(
p
,
'\n'
);
av_new_packet
(
pkt
,
end
?
end
-
p
+
1
:
strlen
(
p
));
pkt
->
flags
|=
AV_PKT_FLAG_KEY
;
pkt
->
pos
=
p
-
ass
->
event_buffer
+
s
->
streams
[
0
]
->
codec
->
extradata_size
;
pkt
->
pts
=
pkt
->
dts
=
get_pts
(
p
);
memcpy
(
pkt
->
data
,
p
,
pkt
->
size
);
ass
->
event_index
++
;
return
0
;
}
}
static
int
read_seek2
(
AVFormatContext
*
s
,
int
stream_index
,
static
int
read_seek2
(
AVFormatContext
*
s
,
int
stream_index
,
int64_t
min_ts
,
int64_t
ts
,
int64_t
max_ts
,
int
flags
)
int64_t
min_ts
,
int64_t
ts
,
int64_t
max_ts
,
int
flags
)
{
{
ASSContext
*
ass
=
s
->
priv_data
;
ASSContext
*
ass
=
s
->
priv_data
;
return
ff_subtitles_queue_seek
(
&
ass
->
q
,
s
,
stream_index
,
if
(
flags
&
AVSEEK_FLAG_BYTE
)
{
min_ts
,
ts
,
max_ts
,
flags
);
return
AVERROR
(
ENOSYS
);
}
else
if
(
flags
&
AVSEEK_FLAG_FRAME
)
{
if
(
ts
<
0
||
ts
>=
ass
->
event_count
)
return
AVERROR
(
ERANGE
);
ass
->
event_index
=
ts
;
}
else
{
int
i
,
idx
=
-
1
;
int64_t
min_ts_diff
=
INT64_MAX
;
if
(
stream_index
==
-
1
)
{
AVRational
time_base
=
s
->
streams
[
0
]
->
time_base
;
ts
=
av_rescale_q
(
ts
,
AV_TIME_BASE_Q
,
time_base
);
min_ts
=
av_rescale_rnd
(
min_ts
,
time_base
.
den
,
time_base
.
num
*
(
int64_t
)
AV_TIME_BASE
,
AV_ROUND_UP
);
max_ts
=
av_rescale_rnd
(
max_ts
,
time_base
.
den
,
time_base
.
num
*
(
int64_t
)
AV_TIME_BASE
,
AV_ROUND_DOWN
);
}
/* TODO: ass->event[] is sorted by pts so we could do a binary search */
for
(
i
=
0
;
i
<
ass
->
event_count
;
i
++
)
{
int64_t
pts
=
get_pts
(
ass
->
event
[
i
]);
int64_t
ts_diff
=
FFABS
(
pts
-
ts
);
if
(
pts
>=
min_ts
&&
pts
<=
max_ts
&&
ts_diff
<
min_ts_diff
)
{
min_ts_diff
=
ts_diff
;
idx
=
i
;
}
}
if
(
idx
<
0
)
return
AVERROR
(
ERANGE
);
ass
->
event_index
=
idx
;
}
return
0
;
}
}
AVInputFormat
ff_ass_demuxer
=
{
AVInputFormat
ff_ass_demuxer
=
{
...
...
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