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