FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
•
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavformat
ffmetadec.c
Go to the documentation of this file.
1
/*
2
* Metadata demuxer
3
* Copyright (c) 2010 Anton Khirnov
4
*
5
* This file is part of FFmpeg.
6
*
7
* FFmpeg is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* FFmpeg is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with FFmpeg; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
22
#include "
libavutil/mathematics.h
"
23
#include "
avformat.h
"
24
#include "
ffmeta.h
"
25
#include "
internal.h
"
26
#include "
libavutil/dict.h
"
27
28
static
int
probe
(
AVProbeData
*p)
29
{
30
if
(!memcmp(p->
buf
,
ID_STRING
, strlen(
ID_STRING
)))
31
return
AVPROBE_SCORE_MAX
;
32
return
0;
33
}
34
35
static
void
get_line
(
AVIOContext
*
s
,
uint8_t
*
buf
,
int
size
)
36
{
37
do
{
38
uint8_t
c
;
39
int
i = 0;
40
41
while
((c =
avio_r8
(s))) {
42
if
(c ==
'\\'
) {
43
if
(i < size - 1)
44
buf[i++] =
c
;
45
c =
avio_r8
(s);
46
}
else
if
(c ==
'\n'
)
47
break
;
48
49
if
(i < size - 1)
50
buf[i++] =
c
;
51
}
52
buf[i] = 0;
53
}
while
(!
url_feof
(s) && (buf[0] ==
';'
|| buf[0] ==
'#'
|| buf[0] == 0));
54
}
55
56
static
AVChapter
*
read_chapter
(
AVFormatContext
*
s
)
57
{
58
uint8_t
line
[256];
59
int64_t
start
,
end
;
60
AVRational
tb
= {1, 1e9};
61
62
get_line
(s->
pb
, line,
sizeof
(line));
63
64
if
(sscanf(line,
"TIMEBASE=%d/%d"
, &tb.
num
, &tb.
den
))
65
get_line
(s->
pb
, line,
sizeof
(line));
66
if
(!sscanf(line,
"START=%"
SCNd64, &start)) {
67
av_log
(s,
AV_LOG_ERROR
,
"Expected chapter start timestamp, found %s.\n"
, line);
68
start = (s->
nb_chapters
&& s->
chapters
[s->
nb_chapters
- 1]->
end
!=
AV_NOPTS_VALUE
) ?
69
s->
chapters
[s->
nb_chapters
- 1]->
end
: 0;
70
}
else
71
get_line
(s->
pb
, line,
sizeof
(line));
72
73
if
(!sscanf(line,
"END=%"
SCNd64, &end)) {
74
av_log
(s,
AV_LOG_ERROR
,
"Expected chapter end timestamp, found %s.\n"
, line);
75
end =
AV_NOPTS_VALUE
;
76
}
77
78
return
avpriv_new_chapter
(s, s->
nb_chapters
, tb, start, end, NULL);
79
}
80
81
static
uint8_t
*
unescape
(
uint8_t
*
buf
,
int
size
)
82
{
83
uint8_t
*
ret
=
av_malloc
(size + 1);
84
uint8_t
*p1 =
ret
, *p2 =
buf
;
85
86
if
(!ret)
87
return
NULL;
88
89
while
(p2 < buf + size) {
90
if
(*p2 ==
'\\'
)
91
p2++;
92
*p1++ = *p2++;
93
}
94
*p1 = 0;
95
return
ret
;
96
}
97
98
static
int
read_tag
(
uint8_t
*
line
,
AVDictionary
**
m
)
99
{
100
uint8_t
*key, *
value
, *p = line;
101
102
/* find first not escaped '=' */
103
while
(1) {
104
if
(*p ==
'='
)
105
break
;
106
else
if
(*p ==
'\\'
)
107
p++;
108
109
if
(*p++)
110
continue
;
111
112
return
0;
113
}
114
115
if
(!(key =
unescape
(line, p - line)))
116
return
AVERROR
(ENOMEM);
117
if
(!(value =
unescape
(p + 1, strlen(p + 1)))) {
118
av_free
(key);
119
return
AVERROR
(ENOMEM);
120
}
121
122
av_dict_set
(m, key, value,
AV_DICT_DONT_STRDUP_KEY
|
AV_DICT_DONT_STRDUP_VAL
);
123
return
0;
124
}
125
126
static
int
read_header
(
AVFormatContext
*
s
)
127
{
128
AVDictionary
**
m
= &s->
metadata
;
129
uint8_t
line
[1024];
130
131
while
(!
url_feof
(s->
pb
)) {
132
get_line
(s->
pb
, line,
sizeof
(line));
133
134
if
(!memcmp(line,
ID_STREAM
, strlen(
ID_STREAM
))) {
135
AVStream
*st =
avformat_new_stream
(s, NULL);
136
137
if
(!st)
138
return
AVERROR
(ENOMEM);
139
140
st->
codec
->
codec_type
=
AVMEDIA_TYPE_DATA
;
141
st->
codec
->
codec_id
=
AV_CODEC_ID_FFMETADATA
;
142
143
m = &st->
metadata
;
144
}
else
if
(!memcmp(line,
ID_CHAPTER
, strlen(
ID_CHAPTER
))) {
145
AVChapter
*ch =
read_chapter
(s);
146
147
if
(!ch)
148
return
AVERROR
(ENOMEM);
149
150
m = &ch->
metadata
;
151
}
else
152
read_tag
(line, m);
153
}
154
155
s->
start_time
= 0;
156
if
(s->
nb_chapters
)
157
s->
duration
=
av_rescale_q
(s->
chapters
[s->
nb_chapters
- 1]->
end
,
158
s->
chapters
[s->
nb_chapters
- 1]->
time_base
,
159
AV_TIME_BASE_Q
);
160
161
return
0;
162
}
163
164
static
int
read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
165
{
166
return
AVERROR_EOF
;
167
}
168
169
AVInputFormat
ff_ffmetadata_demuxer
= {
170
.
name
=
"ffmetadata"
,
171
.long_name =
NULL_IF_CONFIG_SMALL
(
"FFmpeg metadata in text"
),
172
.read_probe =
probe
,
173
.read_header =
read_header
,
174
.read_packet =
read_packet
,
175
};
Generated on Sat Jan 25 2014 19:52:02 for FFmpeg by
1.8.2