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