FFmpeg
Loading...
Searching...
No Matches
rtpdec_qt.c
Go to the documentation of this file.
1/*
2 * RTP/Quicktime support.
3 * Copyright (c) 2009 Ronald S. Bultje
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/**
23 * @file
24 * @brief Quicktime-style RTP support
25 * @author Ronald S. Bultje <rbultje@ronald.bitfreak.net>
26 */
27
28#include "libavutil/mem.h"
29#include "avformat.h"
30#include "internal.h"
31#include "avio_internal.h"
32#include "rtp.h"
33#include "rtpdec.h"
34#include "isom.h"
35#include "libavcodec/get_bits.h"
36
37struct PayloadContext {
40 uint32_t timestamp;
41};
42
43static av_cold int qt_rtp_init(AVFormatContext *ctx, int st_index,
45{
46 qt->pkt = av_packet_alloc();
47 if (!qt->pkt)
48 return AVERROR(ENOMEM);
49
50 return 0;
51}
52
54 AVStream *st, AVPacket *pkt,
55 uint32_t *timestamp, const uint8_t *buf,
56 int len, uint16_t seq, int flags)
57{
58 FFIOContext pb0;
59 AVIOContext *const pb = &pb0.pub;
61 int packing_scheme, has_payload_desc, has_packet_info, alen,
62 has_marker_bit = flags & RTP_FLAG_MARKER,
63 keyframe, ret;
64
65 if (qt->remaining) {
66 int num = qt->pkt->size / qt->bytes_per_frame;
67
68 if ((ret = av_new_packet(pkt, qt->bytes_per_frame)) < 0)
69 return ret;
70 pkt->stream_index = st->index;
71 pkt->flags = qt->pkt->flags;
72 memcpy(pkt->data,
73 &qt->pkt->data[(num - qt->remaining) * qt->bytes_per_frame],
74 qt->bytes_per_frame);
75 if (--qt->remaining == 0) {
76 av_freep(&qt->pkt->data);
77 qt->pkt->size = 0;
78 }
79 return qt->remaining > 0;
80 }
81
82 /**
83 * The RTP payload is described in:
84 * http://developer.apple.com/quicktime/icefloe/dispatch026.html
85 */
86 ret = init_get_bits(&gb, buf, len << 3);
87 if (ret < 0)
88 return ret;
89 ffio_init_read_context(&pb0, buf, len);
90
91 if (len < 4)
93
94 skip_bits(&gb, 4); // version
95 if ((packing_scheme = get_bits(&gb, 2)) == 0)
97 keyframe = get_bits1(&gb);
98 has_payload_desc = get_bits1(&gb);
99 has_packet_info = get_bits1(&gb);
100 skip_bits(&gb, 23); // reserved:7, cache payload info:1, payload ID:15
101
102 if (has_payload_desc) {
103 int data_len, pos, is_start, is_finish;
104 uint32_t tag;
105
106 pos = get_bits_count(&gb) >> 3;
107 if (pos + 12 > len)
108 return AVERROR_INVALIDDATA;
109
110 skip_bits(&gb, 2); // has non-I-frames:1, is sparse:1
111 is_start = get_bits1(&gb);
112 is_finish = get_bits1(&gb);
113 if (!is_start || !is_finish) {
114 avpriv_request_sample(s, "RTP-X-QT with payload description "
115 "split over several packets");
117 }
118 skip_bits(&gb, 12); // reserved
119 data_len = get_bits(&gb, 16);
120
121 avio_seek(pb, pos + 4, SEEK_SET);
122 tag = avio_rl32(pb);
124 tag != MKTAG('v','i','d','e')) ||
126 tag != MKTAG('s','o','u','n')))
127 return AVERROR_INVALIDDATA;
128 avpriv_set_pts_info(st, 32, 1, avio_rb32(pb));
129
130 if (pos + data_len > len)
131 return AVERROR_INVALIDDATA;
132 /* TLVs */
133 while (avio_tell(pb) + 4 < pos + data_len) {
134 int tlv_len = avio_rb16(pb);
135 tag = avio_rl16(pb);
136 if (avio_tell(pb) + tlv_len > pos + data_len)
137 return AVERROR_INVALIDDATA;
138
139#define MKTAG16(a,b) MKTAG(a,b,0,0)
140 switch (tag) {
141 case MKTAG16('s','d'): {
142 MOVStreamContext *msc;
143 void *priv_data = st->priv_data;
144 int nb_streams = s->nb_streams;
145 MOVContext *mc = av_mallocz(sizeof(*mc));
146 if (!mc)
147 return AVERROR(ENOMEM);
148 mc->fc = s;
149 st->priv_data = msc = av_mallocz(sizeof(MOVStreamContext));
150 if (!msc) {
151 av_free(mc);
152 st->priv_data = priv_data;
153 return AVERROR(ENOMEM);
154 }
155 /* ff_mov_read_stsd_entries updates stream s->nb_streams-1,
156 * so set it temporarily to indicate which stream to update. */
157 s->nb_streams = st->index + 1;
160 av_free(msc);
161 av_free(mc);
162 st->priv_data = priv_data;
163 s->nb_streams = nb_streams;
164 break;
165 }
166 default:
167 avio_skip(pb, tlv_len);
168 break;
169 }
170 }
171
172 /* 32-bit alignment */
173 avio_skip(pb, ((avio_tell(pb) + 3) & ~3) - avio_tell(pb));
174 } else
175 avio_seek(pb, 4, SEEK_SET);
176
177 if (has_packet_info) {
178 avpriv_request_sample(s, "RTP-X-QT with packet-specific info");
180 }
181
182 alen = len - avio_tell(pb);
183 if (alen <= 0)
184 return AVERROR_INVALIDDATA;
185
186 switch (packing_scheme) {
187 case 3: /* one data packet spread over 1 or multiple RTP packets */
188 if (qt->pkt->size > 0 && qt->timestamp == *timestamp) {
189 int err;
190 if ((err = av_reallocp(&qt->pkt->data, qt->pkt->size + alen +
192 qt->pkt->size = 0;
193 return err;
194 }
195 } else {
196 av_freep(&qt->pkt->data);
197 av_packet_unref(qt->pkt);
199 if (!qt->pkt->data)
200 return AVERROR(ENOMEM);
201 qt->pkt->size = 0;
202 qt->timestamp = *timestamp;
203 }
204 memcpy(qt->pkt->data + qt->pkt->size, buf + avio_tell(pb), alen);
205 qt->pkt->size += alen;
206 if (has_marker_bit) {
207 int ret = av_packet_from_data(pkt, qt->pkt->data, qt->pkt->size);
208 if (ret < 0)
209 return ret;
210
211 qt->pkt->size = 0;
212 qt->pkt->data = NULL;
213 pkt->flags = keyframe ? AV_PKT_FLAG_KEY : 0;
214 pkt->stream_index = st->index;
215 memset(pkt->data + pkt->size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
216 return 0;
217 }
218 return AVERROR(EAGAIN);
219
220 case 1: /* constant packet size, multiple packets per RTP packet */
221 if (qt->bytes_per_frame == 0 ||
222 alen % qt->bytes_per_frame != 0)
223 return AVERROR_INVALIDDATA; /* wrongly padded */
224 qt->remaining = (alen / qt->bytes_per_frame) - 1;
225 if ((ret = av_new_packet(pkt, qt->bytes_per_frame)) < 0)
226 return ret;
227 memcpy(pkt->data, buf + avio_tell(pb), qt->bytes_per_frame);
228 pkt->flags = keyframe ? AV_PKT_FLAG_KEY : 0;
229 pkt->stream_index = st->index;
230 if (qt->remaining > 0) {
231 av_freep(&qt->pkt->data);
232 qt->pkt->data = av_realloc(NULL, qt->remaining * qt->bytes_per_frame);
233 if (!qt->pkt->data) {
235 return AVERROR(ENOMEM);
236 }
237 qt->pkt->size = qt->remaining * qt->bytes_per_frame;
238 memcpy(qt->pkt->data,
239 buf + avio_tell(pb) + qt->bytes_per_frame,
240 qt->remaining * qt->bytes_per_frame);
241 qt->pkt->flags = pkt->flags;
242 return 1;
243 }
244 return 0;
245
246 default: /* unimplemented */
247 avpriv_request_sample(NULL, "RTP-X-QT with packing scheme 2");
249 }
250}
251
253{
254 av_freep(&qt->pkt->data);
255 av_packet_free(&qt->pkt);
256}
257
258#define RTP_QT_HANDLER(m, n, s, t) \
259const RTPDynamicProtocolHandler ff_ ## m ## _rtp_ ## n ## _handler = { \
260 .enc_name = s, \
261 .codec_type = t, \
262 .codec_id = AV_CODEC_ID_NONE, \
263 .priv_data_size = sizeof(PayloadContext), \
264 .init = qt_rtp_init, \
265 .close = qt_rtp_close, \
266 .parse_packet = qt_rtp_parse_packet, \
267}
268
271RTP_QT_HANDLER(quicktime, vid, "X-QUICKTIME", AVMEDIA_TYPE_VIDEO);
272RTP_QT_HANDLER(quicktime, aud, "X-QUICKTIME", AVMEDIA_TYPE_AUDIO);
static AVFormatContext * ctx
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition avformat.c:834
Main libavformat public API header.
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition aviobuf.c:236
unsigned int avio_rb16(AVIOContext *s)
Definition aviobuf.c:749
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition avio.h:494
unsigned int avio_rl16(AVIOContext *s)
Definition aviobuf.c:717
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition aviobuf.c:321
unsigned int avio_rl32(AVIOContext *s)
Definition aviobuf.c:733
unsigned int avio_rb32(AVIOContext *s)
Definition aviobuf.c:764
void ffio_init_read_context(FFIOContext *s, const uint8_t *buffer, int buffer_size)
Wrap a buffer in an AVIOContext for reading.
Definition aviobuf.c:99
#define flags(name, subs,...)
Definition cbs_h264.c:74
static int FUNC aud(CodedBitstreamContext *ctx, RWContext *rw, H264RawAUD *current)
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
static AVPacket * pkt
static unsigned int nb_streams
Definition ffprobe.c:352
bitstream reader API header.
static unsigned int get_bits1(GetBitContext *s)
Definition get_bits.h:391
static void skip_bits(GetBitContext *s, int n)
Definition get_bits.h:383
static int get_bits_count(const GetBitContext *s)
Definition get_bits.h:254
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition get_bits.h:337
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition get_bits.h:517
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding.
Definition defs.h:40
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition packet.c:74
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition packet.c:434
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition packet.h:650
int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size)
Initialize a reference-counted packet from av_malloc()ed data.
Definition packet.c:172
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition packet.c:63
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition packet.c:98
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition error.h:64
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR(e)
Definition error.h:45
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition mem.c:188
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
Definition mov.c:3350
#define av_cold
Definition attributes.h:117
#define MKTAG(a, b, c, d)
Definition macros.h:55
Memory handling functions.
uint32_t tag
Definition movenc.c:2087
#define av_realloc(p, s)
Definition ops_static.c:54
#define RTP_FLAG_MARKER
RTP marker bit was set for this packet.
Definition rtpdec.h:94
static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, uint16_t seq, int flags)
Definition rtpdec_qt.c:53
static av_cold int qt_rtp_init(AVFormatContext *ctx, int st_index, PayloadContext *qt)
Definition rtpdec_qt.c:43
#define RTP_QT_HANDLER(m, n, s, t)
Definition rtpdec_qt.c:258
static void qt_rtp_close(PayloadContext *qt)
Definition rtpdec_qt.c:252
#define MKTAG16(a, b)
unsigned int pos
Definition spdifenc.c:431
enum AVMediaType codec_type
General type of the encoded data.
Definition codec_par.h:53
Format I/O context.
Definition avformat.h:1333
Bytestream IO Context.
Definition avio.h:160
This structure stores compressed data.
Definition packet.h:580
int flags
A combination of AV_PKT_FLAG values.
Definition packet.h:609
int size
Definition packet.h:604
uint8_t * data
Definition packet.h:603
Stream structure.
Definition avformat.h:766
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:789
void * priv_data
Definition avformat.h:791
int index
stream index in AVFormatContext
Definition avformat.h:772
AVIOContext pub
unsigned int bytes_per_frame
Definition isom.h:223
RTP/AV1 specific private data.
Definition rdt.c:85
AVPacket * pkt
Definition rtpdec_qt.c:38
uint32_t timestamp
last received timestamp for frame
Definition rtpdec_ac3.c:31
int bytes_per_frame
Definition rtpdec_qt.c:39
#define av_free(p)
#define av_mallocz(s)
#define avpriv_request_sample(...)
#define av_freep(p)
#define mc
int len