Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
rtpdec_vp8.c
Go to the documentation of this file.
1
/*
2
* RTP VP8 Depacketizer
3
* Copyright (c) 2010 Josh Allmann
4
*
5
* This file is part of Libav.
6
*
7
* Libav 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
* Libav 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 Libav; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
29
#include "
libavcodec/bytestream.h
"
30
31
#include "
rtpdec_formats.h
"
32
33
struct
PayloadContext
{
34
AVIOContext
*
data
;
35
uint32_t
timestamp
;
36
int
is_keyframe
;
37
};
38
39
static
void
prepare_packet
(
AVPacket
*pkt,
PayloadContext
*vp8,
int
stream)
40
{
41
av_init_packet
(pkt);
42
pkt->
stream_index
= stream;
43
pkt->
flags
= vp8->
is_keyframe
?
AV_PKT_FLAG_KEY
: 0;
44
pkt->
size
=
avio_close_dyn_buf
(vp8->
data
, &pkt->
data
);
45
pkt->
destruct
=
av_destruct_packet
;
46
vp8->
data
=
NULL
;
47
}
48
49
static
int
vp8_handle_packet
(
AVFormatContext
*ctx,
50
PayloadContext
*vp8,
51
AVStream
*st,
52
AVPacket
*pkt,
53
uint32_t *timestamp,
54
const
uint8_t *buf,
55
int
len
,
int
flags
)
56
{
57
int
start_packet, end_packet, has_au, ret =
AVERROR
(EAGAIN);
58
59
if
(!buf) {
60
// only called when vp8_handle_packet returns 1
61
if
(!vp8->
data
) {
62
av_log
(ctx,
AV_LOG_ERROR
,
"Invalid VP8 data passed\n"
);
63
return
AVERROR_INVALIDDATA
;
64
}
65
prepare_packet
(pkt, vp8, st->
index
);
66
*timestamp = vp8->
timestamp
;
67
return
0;
68
}
69
70
start_packet = *buf & 1;
71
end_packet = flags &
RTP_FLAG_MARKER
;
72
has_au = *buf & 2;
73
buf++;
74
len--;
75
76
if
(start_packet) {
77
int
res;
78
uint32_t ts = *timestamp;
79
if
(vp8->
data
) {
80
// missing end marker; return old frame anyway. untested
81
prepare_packet
(pkt, vp8, st->
index
);
82
*timestamp = vp8->
timestamp
;
// reset timestamp from old frame
83
84
// if current frame fits into one rtp packet, need to hold
85
// that for the next av_get_packet call
86
ret = end_packet ? 1 : 0;
87
}
88
if
((res =
avio_open_dyn_buf
(&vp8->
data
)) < 0)
89
return
res;
90
vp8->
is_keyframe
= *buf & 1;
91
vp8->
timestamp
= ts;
92
}
93
94
if
(!vp8->
data
|| vp8->
timestamp
!= *timestamp && ret ==
AVERROR
(EAGAIN)) {
95
av_log
(ctx,
AV_LOG_WARNING
,
96
"Received no start marker; dropping frame\n"
);
97
return
AVERROR
(EAGAIN);
98
}
99
100
// cycle through VP8AU headers if needed
101
// not tested with actual VP8AUs
102
while
(len) {
103
int
au_len =
len
;
104
if
(has_au && len > 2) {
105
au_len =
AV_RB16
(buf);
106
buf += 2;
107
len -= 2;
108
if
(buf + au_len > buf + len) {
109
av_log
(ctx,
AV_LOG_ERROR
,
"Invalid VP8AU length\n"
);
110
return
AVERROR_INVALIDDATA
;
111
}
112
}
113
114
avio_write
(vp8->
data
, buf, au_len);
115
buf += au_len;
116
len -= au_len;
117
}
118
119
if
(ret !=
AVERROR
(EAGAIN))
// did we miss a end marker?
120
return
ret;
121
122
if
(end_packet) {
123
prepare_packet
(pkt, vp8, st->
index
);
124
return
0;
125
}
126
127
return
AVERROR
(EAGAIN);
128
}
129
130
static
PayloadContext
*
vp8_new_context
(
void
)
131
{
132
av_log
(
NULL
,
AV_LOG_ERROR
,
"RTP VP8 payload implementation is incompatible "
133
"with the latest spec drafts.\n"
);
134
return
av_mallocz
(
sizeof
(
PayloadContext
));
135
}
136
137
static
void
vp8_free_context
(
PayloadContext
*vp8)
138
{
139
if
(vp8->
data
) {
140
uint8_t *tmp;
141
avio_close_dyn_buf
(vp8->
data
, &tmp);
142
av_free
(tmp);
143
}
144
av_free
(vp8);
145
}
146
147
RTPDynamicProtocolHandler
ff_vp8_dynamic_handler
= {
148
.
enc_name
=
"VP8"
,
149
.codec_type =
AVMEDIA_TYPE_VIDEO
,
150
.codec_id =
CODEC_ID_VP8
,
151
.alloc =
vp8_new_context
,
152
.free =
vp8_free_context
,
153
.parse_packet =
vp8_handle_packet
,
154
};