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
c0fb6f96
Commit
c0fb6f96
authored
Dec 16, 2018
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avformat/vorbiscomment: add support for writing chapters
Fixes #7532.
parent
d283ee08
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
79 additions
and
19 deletions
+79
-19
flacenc.c
libavformat/flacenc.c
+2
-2
matroskaenc.c
libavformat/matroskaenc.c
+2
-2
oggenc.c
libavformat/oggenc.c
+12
-10
vorbiscomment.c
libavformat/vorbiscomment.c
+57
-3
vorbiscomment.h
libavformat/vorbiscomment.h
+6
-2
No files found.
libavformat/flacenc.c
View file @
c0fb6f96
...
...
@@ -65,7 +65,7 @@ static int flac_write_block_comment(AVIOContext *pb, AVDictionary **m,
ff_metadata_conv
(
m
,
ff_vorbiscomment_metadata_conv
,
NULL
);
len
=
ff_vorbiscomment_length
(
*
m
,
vendor
);
len
=
ff_vorbiscomment_length
(
*
m
,
vendor
,
NULL
,
0
);
if
(
len
>=
((
1
<<
24
)
-
4
))
return
AVERROR
(
EINVAL
);
p0
=
av_malloc
(
len
+
4
);
...
...
@@ -75,7 +75,7 @@ static int flac_write_block_comment(AVIOContext *pb, AVDictionary **m,
bytestream_put_byte
(
&
p
,
last_block
?
0x84
:
0x04
);
bytestream_put_be24
(
&
p
,
len
);
ff_vorbiscomment_write
(
&
p
,
m
,
vendor
);
ff_vorbiscomment_write
(
&
p
,
m
,
vendor
,
NULL
,
0
);
avio_write
(
pb
,
p0
,
len
+
4
);
av_freep
(
&
p0
);
...
...
libavformat/matroskaenc.c
View file @
c0fb6f96
...
...
@@ -693,7 +693,7 @@ static int put_flac_codecpriv(AVFormatContext *s,
snprintf
(
buf
,
sizeof
(
buf
),
"0x%"
PRIx64
,
par
->
channel_layout
);
av_dict_set
(
&
dict
,
"WAVEFORMATEXTENSIBLE_CHANNEL_MASK"
,
buf
,
0
);
len
=
ff_vorbiscomment_length
(
dict
,
vendor
);
len
=
ff_vorbiscomment_length
(
dict
,
vendor
,
NULL
,
0
);
if
(
len
>=
((
1
<<
24
)
-
4
))
return
AVERROR
(
EINVAL
);
...
...
@@ -707,7 +707,7 @@ static int put_flac_codecpriv(AVFormatContext *s,
AV_WB24
(
data
+
1
,
len
);
p
=
data
+
4
;
ff_vorbiscomment_write
(
&
p
,
&
dict
,
vendor
);
ff_vorbiscomment_write
(
&
p
,
&
dict
,
vendor
,
NULL
,
0
);
avio_write
(
pb
,
data
,
len
+
4
);
...
...
libavformat/oggenc.c
View file @
c0fb6f96
...
...
@@ -291,7 +291,8 @@ static int ogg_buffer_data(AVFormatContext *s, AVStream *st,
}
static
uint8_t
*
ogg_write_vorbiscomment
(
int64_t
offset
,
int
bitexact
,
int
*
header_len
,
AVDictionary
**
m
,
int
framing_bit
)
int
*
header_len
,
AVDictionary
**
m
,
int
framing_bit
,
AVChapter
**
chapters
,
unsigned
int
nb_chapters
)
{
const
char
*
vendor
=
bitexact
?
"ffmpeg"
:
LIBAVFORMAT_IDENT
;
int64_t
size
;
...
...
@@ -299,7 +300,7 @@ static uint8_t *ogg_write_vorbiscomment(int64_t offset, int bitexact,
ff_metadata_conv
(
m
,
ff_vorbiscomment_metadata_conv
,
NULL
);
size
=
offset
+
ff_vorbiscomment_length
(
*
m
,
vendor
)
+
framing_bit
;
size
=
offset
+
ff_vorbiscomment_length
(
*
m
,
vendor
,
chapters
,
nb_chapters
)
+
framing_bit
;
if
(
size
>
INT_MAX
)
return
NULL
;
p
=
av_mallocz
(
size
);
...
...
@@ -308,7 +309,7 @@ static uint8_t *ogg_write_vorbiscomment(int64_t offset, int bitexact,
p0
=
p
;
p
+=
offset
;
ff_vorbiscomment_write
(
&
p
,
m
,
vendor
);
ff_vorbiscomment_write
(
&
p
,
m
,
vendor
,
chapters
,
nb_chapters
);
if
(
framing_bit
)
bytestream_put_byte
(
&
p
,
1
);
...
...
@@ -342,7 +343,7 @@ static int ogg_build_flac_headers(AVCodecParameters *par,
bytestream_put_buffer
(
&
p
,
par
->
extradata
,
FLAC_STREAMINFO_SIZE
);
// second packet: VorbisComment
p
=
ogg_write_vorbiscomment
(
4
,
bitexact
,
&
oggstream
->
header_len
[
1
],
m
,
0
);
p
=
ogg_write_vorbiscomment
(
4
,
bitexact
,
&
oggstream
->
header_len
[
1
],
m
,
0
,
NULL
,
0
);
if
(
!
p
)
return
AVERROR
(
ENOMEM
);
oggstream
->
header
[
1
]
=
p
;
...
...
@@ -373,7 +374,7 @@ static int ogg_build_speex_headers(AVCodecParameters *par,
AV_WL32
(
&
oggstream
->
header
[
0
][
68
],
0
);
// set extra_headers to 0
// second packet: VorbisComment
p
=
ogg_write_vorbiscomment
(
0
,
bitexact
,
&
oggstream
->
header_len
[
1
],
m
,
0
);
p
=
ogg_write_vorbiscomment
(
0
,
bitexact
,
&
oggstream
->
header_len
[
1
],
m
,
0
,
NULL
,
0
);
if
(
!
p
)
return
AVERROR
(
ENOMEM
);
oggstream
->
header
[
1
]
=
p
;
...
...
@@ -385,7 +386,8 @@ static int ogg_build_speex_headers(AVCodecParameters *par,
static
int
ogg_build_opus_headers
(
AVCodecParameters
*
par
,
OGGStreamContext
*
oggstream
,
int
bitexact
,
AVDictionary
**
m
)
AVDictionary
**
m
,
AVChapter
**
chapters
,
unsigned
int
nb_chapters
)
{
uint8_t
*
p
;
...
...
@@ -401,7 +403,7 @@ static int ogg_build_opus_headers(AVCodecParameters *par,
bytestream_put_buffer
(
&
p
,
par
->
extradata
,
par
->
extradata_size
);
/* second packet: VorbisComment */
p
=
ogg_write_vorbiscomment
(
8
,
bitexact
,
&
oggstream
->
header_len
[
1
],
m
,
0
);
p
=
ogg_write_vorbiscomment
(
8
,
bitexact
,
&
oggstream
->
header_len
[
1
],
m
,
0
,
chapters
,
nb_chapters
);
if
(
!
p
)
return
AVERROR
(
ENOMEM
);
oggstream
->
header
[
1
]
=
p
;
...
...
@@ -446,7 +448,7 @@ static int ogg_build_vp8_headers(AVFormatContext *s, AVStream *st,
/* optional second packet: VorbisComment */
if
(
av_dict_get
(
st
->
metadata
,
""
,
NULL
,
AV_DICT_IGNORE_SUFFIX
))
{
p
=
ogg_write_vorbiscomment
(
7
,
bitexact
,
&
oggstream
->
header_len
[
1
],
&
st
->
metadata
,
0
);
p
=
ogg_write_vorbiscomment
(
7
,
bitexact
,
&
oggstream
->
header_len
[
1
],
&
st
->
metadata
,
0
,
NULL
,
0
);
if
(
!
p
)
return
AVERROR
(
ENOMEM
);
oggstream
->
header
[
1
]
=
p
;
...
...
@@ -560,7 +562,7 @@ static int ogg_init(AVFormatContext *s)
}
else
if
(
st
->
codecpar
->
codec_id
==
AV_CODEC_ID_OPUS
)
{
int
err
=
ogg_build_opus_headers
(
st
->
codecpar
,
oggstream
,
s
->
flags
&
AVFMT_FLAG_BITEXACT
,
&
st
->
metadata
);
&
st
->
metadata
,
s
->
chapters
,
s
->
nb_chapters
);
if
(
err
)
{
av_log
(
s
,
AV_LOG_ERROR
,
"Error writing Opus headers
\n
"
);
av_freep
(
&
st
->
priv_data
);
...
...
@@ -590,7 +592,7 @@ static int ogg_init(AVFormatContext *s)
p
=
ogg_write_vorbiscomment
(
7
,
s
->
flags
&
AVFMT_FLAG_BITEXACT
,
&
oggstream
->
header_len
[
1
],
&
st
->
metadata
,
framing_bit
);
framing_bit
,
NULL
,
0
);
oggstream
->
header
[
1
]
=
p
;
if
(
!
p
)
return
AVERROR
(
ENOMEM
);
...
...
libavformat/vorbiscomment.c
View file @
c0fb6f96
...
...
@@ -38,10 +38,21 @@ const AVMetadataConv ff_vorbiscomment_metadata_conv[] = {
{
0
}
};
int64_t
ff_vorbiscomment_length
(
AVDictionary
*
m
,
const
char
*
vendor_string
)
int64_t
ff_vorbiscomment_length
(
AVDictionary
*
m
,
const
char
*
vendor_string
,
AVChapter
**
chapters
,
unsigned
int
nb_chapters
)
{
int64_t
len
=
8
;
len
+=
strlen
(
vendor_string
);
if
(
chapters
&&
nb_chapters
)
{
for
(
int
i
=
0
;
i
<
nb_chapters
;
i
++
)
{
AVDictionaryEntry
*
tag
=
NULL
;
len
+=
4
+
12
+
1
+
10
;
while
((
tag
=
av_dict_get
(
chapters
[
i
]
->
metadata
,
""
,
tag
,
AV_DICT_IGNORE_SUFFIX
)))
{
int64_t
len1
=
!
strcmp
(
tag
->
key
,
"title"
)
?
4
:
strlen
(
tag
->
key
);
len
+=
4
+
10
+
len1
+
1
+
strlen
(
tag
->
value
);
}
}
}
if
(
m
)
{
AVDictionaryEntry
*
tag
=
NULL
;
while
((
tag
=
av_dict_get
(
m
,
""
,
tag
,
AV_DICT_IGNORE_SUFFIX
)))
{
...
...
@@ -52,12 +63,19 @@ int64_t ff_vorbiscomment_length(AVDictionary *m, const char *vendor_string)
}
int
ff_vorbiscomment_write
(
uint8_t
**
p
,
AVDictionary
**
m
,
const
char
*
vendor_string
)
const
char
*
vendor_string
,
AVChapter
**
chapters
,
unsigned
int
nb_chapters
)
{
int
cm_count
=
0
;
bytestream_put_le32
(
p
,
strlen
(
vendor_string
));
bytestream_put_buffer
(
p
,
vendor_string
,
strlen
(
vendor_string
));
if
(
chapters
&&
nb_chapters
)
{
for
(
int
i
=
0
;
i
<
nb_chapters
;
i
++
)
{
cm_count
+=
av_dict_count
(
chapters
[
i
]
->
metadata
)
+
1
;
}
}
if
(
*
m
)
{
int
count
=
av_dict_count
(
*
m
);
int
count
=
av_dict_count
(
*
m
)
+
cm_count
;
AVDictionaryEntry
*
tag
=
NULL
;
bytestream_put_le32
(
p
,
count
);
while
((
tag
=
av_dict_get
(
*
m
,
""
,
tag
,
AV_DICT_IGNORE_SUFFIX
)))
{
...
...
@@ -70,6 +88,42 @@ int ff_vorbiscomment_write(uint8_t **p, AVDictionary **m,
bytestream_put_byte
(
p
,
'='
);
bytestream_put_buffer
(
p
,
tag
->
value
,
len2
);
}
for
(
int
i
=
0
;
i
<
nb_chapters
;
i
++
)
{
AVChapter
*
chp
=
chapters
[
i
];
char
chapter_time
[
13
];
char
chapter_number
[
4
];
int
h
,
m
,
s
,
ms
;
s
=
av_rescale
(
chp
->
start
,
chp
->
time_base
.
num
,
chp
->
time_base
.
den
);
h
=
s
/
3600
;
m
=
(
s
/
60
)
%
60
;
ms
=
av_rescale_q
(
chp
->
start
,
chp
->
time_base
,
av_make_q
(
1
,
1000
))
%
1000
;
s
=
s
%
60
;
snprintf
(
chapter_number
,
sizeof
(
chapter_number
),
"%03d"
,
i
);
snprintf
(
chapter_time
,
sizeof
(
chapter_time
),
"%02d:%02d:%02d.%03d"
,
h
,
m
,
s
,
ms
);
bytestream_put_le32
(
p
,
10
+
1
+
12
);
bytestream_put_buffer
(
p
,
"CHAPTER"
,
7
);
bytestream_put_buffer
(
p
,
chapter_number
,
3
);
bytestream_put_byte
(
p
,
'='
);
bytestream_put_buffer
(
p
,
chapter_time
,
12
);
tag
=
NULL
;
while
((
tag
=
av_dict_get
(
chapters
[
i
]
->
metadata
,
""
,
tag
,
AV_DICT_IGNORE_SUFFIX
)))
{
int64_t
len1
=
!
strcmp
(
tag
->
key
,
"title"
)
?
4
:
strlen
(
tag
->
key
);
int64_t
len2
=
strlen
(
tag
->
value
);
if
(
len1
+
1
+
len2
+
10
>
UINT32_MAX
)
return
AVERROR
(
EINVAL
);
bytestream_put_le32
(
p
,
10
+
len1
+
1
+
len2
);
bytestream_put_buffer
(
p
,
"CHAPTER"
,
7
);
bytestream_put_buffer
(
p
,
chapter_number
,
3
);
if
(
!
strcmp
(
tag
->
key
,
"title"
))
bytestream_put_buffer
(
p
,
"NAME"
,
4
);
else
bytestream_put_buffer
(
p
,
tag
->
key
,
len1
);
bytestream_put_byte
(
p
,
'='
);
bytestream_put_buffer
(
p
,
tag
->
value
,
len2
);
}
}
}
else
bytestream_put_le32
(
p
,
0
);
return
0
;
...
...
libavformat/vorbiscomment.h
View file @
c0fb6f96
...
...
@@ -34,7 +34,8 @@
* For no string, set to an empty string.
* @return The length in bytes.
*/
int64_t
ff_vorbiscomment_length
(
AVDictionary
*
m
,
const
char
*
vendor_string
);
int64_t
ff_vorbiscomment_length
(
AVDictionary
*
m
,
const
char
*
vendor_string
,
AVChapter
**
chapters
,
unsigned
int
nb_chapters
);
/**
* Write a VorbisComment into a buffer. The buffer, p, must have enough
...
...
@@ -45,9 +46,12 @@ int64_t ff_vorbiscomment_length(AVDictionary *m, const char *vendor_string);
* @param p The buffer in which to write.
* @param m The metadata struct to write.
* @param vendor_string The vendor string to write.
* @param chapters The chapters to write.
* @param nb_chapters The number of chapters to write.
*/
int
ff_vorbiscomment_write
(
uint8_t
**
p
,
AVDictionary
**
m
,
const
char
*
vendor_string
);
const
char
*
vendor_string
,
AVChapter
**
chapters
,
unsigned
int
nb_chapters
);
extern
const
AVMetadataConv
ff_vorbiscomment_metadata_conv
[];
...
...
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