FFmpeg  4.4.7
rtpdec_rfc4175.c
Go to the documentation of this file.
1 /*
2  * RTP Depacketization of RAW video (TR-03)
3  * Copyright (c) 2016 Savoir-faire Linux, Inc
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 /* Development sponsored by CBC/Radio-Canada */
23 
24 #include "avio_internal.h"
25 #include "rtpdec_formats.h"
26 #include "libavutil/avassert.h"
27 #include "libavutil/avstring.h"
28 #include "libavutil/imgutils.h"
29 #include "libavutil/pixdesc.h"
30 
31 struct PayloadContext {
32  char *sampling;
33  int depth;
34  int width;
35  int height;
36 
38  unsigned int frame_size;
39  unsigned int pgroup; /* size of the pixel group in bytes */
40  unsigned int xinc;
41 
42  uint32_t timestamp;
43 };
44 
46 {
48  int bits_per_sample = 0;
49  int tag = 0;
50 
51  if (!strncmp(data->sampling, "YCbCr-4:2:2", 11)) {
52  tag = MKTAG('U', 'Y', 'V', 'Y');
53  data->xinc = 2;
54 
55  if (data->depth == 8) {
56  data->pgroup = 4;
57  bits_per_sample = 16;
59  } else if (data->depth == 10) {
60  data->pgroup = 5;
61  bits_per_sample = 20;
63  } else {
64  return AVERROR_INVALIDDATA;
65  }
66  } else {
67  return AVERROR_INVALIDDATA;
68  }
69 
70  stream->codecpar->format = pixfmt;
71  stream->codecpar->codec_tag = tag;
72  stream->codecpar->bits_per_coded_sample = bits_per_sample;
73  data->frame_size = data->width * data->height * data->pgroup / data->xinc;
74 
75  return 0;
76 }
77 
79  PayloadContext *data, const char *attr,
80  const char *value)
81 {
82  if (!strncmp(attr, "width", 5))
83  data->width = atoi(value);
84  else if (!strncmp(attr, "height", 6))
85  data->height = atoi(value);
86  else if (data->sampling == NULL && !strncmp(attr, "sampling", 8))
87  data->sampling = av_strdup(value);
88  else if (!strncmp(attr, "depth", 5))
89  data->depth = atoi(value);
90 
91  return 0;
92 }
93 
94 static int rfc4175_parse_sdp_line(AVFormatContext *s, int st_index,
95  PayloadContext *data_arg, const char *line)
96 {
97  const char *p;
98 
99  if (st_index < 0)
100  return 0;
101 
102  av_assert0(!data_arg->sampling);
103 
104  if (av_strstart(line, "fmtp:", &p)) {
105  AVStream *stream = s->streams[st_index];
106  PayloadContext data0 = *data_arg, *data = &data0;
107  int ret = ff_parse_fmtp(s, stream, data, p, rfc4175_parse_fmtp);
108 
109  if (!data->sampling || !data->depth || !data->width || !data->height)
110  ret = AVERROR(EINVAL);
111 
112  if (ret < 0)
113  goto fail;
114 
115  ret = av_image_check_size(data->width, data->height, 0, s);
116  if (ret < 0)
117  goto fail;
118 
119  stream->codecpar->width = data->width;
120  stream->codecpar->height = data->height;
121 
122  ret = rfc4175_parse_format(stream, data);
123  av_freep(&data->sampling);
124  if (ret >= 0)
125  *data_arg = *data;
126 fail:
127  av_freep(&data->sampling);
128  return ret;
129  }
130 
131  return 0;
132 }
133 
135  int stream_index)
136 {
137  int ret;
138 
139  pkt->stream_index = stream_index;
140  ret = av_packet_from_data(pkt, data->frame, data->frame_size);
141  if (ret < 0) {
142  av_freep(&data->frame);
143  }
144 
145  data->frame = NULL;
146 
147  return ret;
148 }
149 
151  AVStream *st, AVPacket *pkt, uint32_t *timestamp,
152  const uint8_t * buf, int len,
153  uint16_t seq, int flags)
154 {
155  int length, line, offset, cont;
156  const uint8_t *headers = buf + 2; /* skip extended seqnum */
157  const uint8_t *payload = buf + 2;
158  int payload_len = len - 2;
159  int missed_last_packet = 0;
160 
161  uint8_t *dest;
162 
163  if (*timestamp != data->timestamp) {
164  if (data->frame) {
165  /*
166  * if we're here, it means that two RTP packets didn't have the
167  * same timestamp, which is a sign that they were packets from two
168  * different frames, but we didn't get the flag RTP_FLAG_MARKER on
169  * the first one of these frames (last packet of a frame).
170  * Finalize the previous frame anyway by filling the AVPacket.
171  */
172  av_log(ctx, AV_LOG_ERROR, "Missed previous RTP Marker\n");
173  missed_last_packet = 1;
175  }
176 
177  data->frame = av_malloc(data->frame_size);
178 
179  data->timestamp = *timestamp;
180 
181  if (!data->frame) {
182  av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
183  return AVERROR(ENOMEM);
184  }
185  }
186 
187  /*
188  * looks for the 'Continuation bit' in scan lines' headers
189  * to find where data start
190  */
191  do {
192  if (payload_len < 6)
193  return AVERROR_INVALIDDATA;
194 
195  cont = payload[4] & 0x80;
196  payload += 6;
197  payload_len -= 6;
198  } while (cont);
199 
200  /* and now iterate over every scan lines */
201  do {
202  int copy_offset;
203 
204  if (payload_len < data->pgroup)
205  return AVERROR_INVALIDDATA;
206 
207  length = (headers[0] << 8) | headers[1];
208  line = ((headers[2] & 0x7f) << 8) | headers[3];
209  offset = ((headers[4] & 0x7f) << 8) | headers[5];
210  cont = headers[4] & 0x80;
211  headers += 6;
212 
213  if (length % data->pgroup)
214  return AVERROR_INVALIDDATA;
215 
216  if (length > payload_len)
217  length = payload_len;
218 
219  if (line >= data->height)
220  return AVERROR_INVALIDDATA;
221 
222  /* prevent ill-formed packets to write after buffer's end */
223  copy_offset = (line * data->width + offset) * data->pgroup / data->xinc;
224  if (copy_offset + length > data->frame_size)
225  return AVERROR_INVALIDDATA;
226 
227  dest = data->frame + copy_offset;
228  memcpy(dest, payload, length);
229 
230  payload += length;
231  payload_len -= length;
232  } while (cont);
233 
234  if ((flags & RTP_FLAG_MARKER)) {
235  return rfc4175_finalize_packet(data, pkt, st->index);
236  } else if (missed_last_packet) {
237  return 0;
238  }
239 
240  return AVERROR(EAGAIN);
241 }
242 
244  .enc_name = "raw",
245  .codec_type = AVMEDIA_TYPE_VIDEO,
246  .codec_id = AV_CODEC_ID_BITPACKED,
247  .priv_data_size = sizeof(PayloadContext),
248  .parse_sdp_a_line = rfc4175_parse_sdp_line,
250 };
uint8_t
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
#define flags(name, subs,...)
Definition: cbs_av1.c:572
#define s(width, name)
Definition: cbs_vp9.c:257
#define fail()
Definition: checkasm.h:133
#define MKTAG(a, b, c, d)
Definition: common.h:478
#define NULL
Definition: coverity.c:32
double value
Definition: eval.c:100
@ AV_CODEC_ID_BITPACKED
Definition: codec_id.h:280
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
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
#define AVERROR(e)
Definition: error.h:43
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:253
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition: imgutils.c:317
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition: avstring.c:34
misc image utilities
enum AVPixelFormat pixfmt
Definition: kmsgrab.c:365
static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index, int flush)
Parse a packet, add all split parts to parse_queue.
Definition: utils.c:1423
uint32_t tag
Definition: movenc.c:1611
const char data[16]
Definition: mxf.c:142
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:400
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition: pixfmt.h:81
int ff_parse_fmtp(AVFormatContext *s, AVStream *stream, PayloadContext *data, const char *p, int(*parse_fmtp)(AVFormatContext *s, AVStream *stream, PayloadContext *data, const char *attr, const char *value))
Definition: rtpdec.c:926
#define RTP_FLAG_MARKER
RTP marker bit was set for this packet.
Definition: rtpdec.h:93
static int rfc4175_parse_fmtp(AVFormatContext *s, AVStream *stream, PayloadContext *data, const char *attr, const char *value)
static int rfc4175_finalize_packet(PayloadContext *data, AVPacket *pkt, int stream_index)
static int rfc4175_parse_sdp_line(AVFormatContext *s, int st_index, PayloadContext *data_arg, const char *line)
static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, uint16_t seq, int flags)
static int rfc4175_parse_format(AVStream *stream, PayloadContext *data)
const RTPDynamicProtocolHandler ff_rfc4175_rtp_handler
int bits_per_coded_sample
The number of bits per sample in the codedwords.
Definition: codec_par.h:102
int width
Video only.
Definition: codec_par.h:126
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: codec_par.h:64
Format I/O context.
Definition: avformat.h:1232
This structure stores compressed data.
Definition: packet.h:346
int stream_index
Definition: packet.h:371
Stream structure.
Definition: avformat.h:873
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1038
int index
stream index in AVFormatContext
Definition: avformat.h:874
RTP/JPEG specific private data.
Definition: rdt.c:83
uint32_t timestamp
current frame timestamp
Definition: rtpdec_ac3.c:31
unsigned int xinc
unsigned int frame_size
uint8_t * frame
unsigned int pgroup
const char * enc_name
Definition: rtpdec.h:116
Definition: graph2dot.c:48
#define av_freep(p)
#define av_malloc(s)
#define av_log(a,...)
AVPacket * pkt
Definition: movenc.c:59
AVFormatContext * ctx
Definition: movenc.c:48
if(ret< 0)
Definition: vf_mcdeint.c:282
static const uint8_t offset[127][2]
Definition: vf_spp.c:107
int len