FFmpeg
mpjpegdec.c
Go to the documentation of this file.
1 /*
2  * Multipart JPEG format
3  * Copyright (c) 2015 Luca Barbato
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/avstring.h"
23 #include "libavutil/opt.h"
24 
25 #include "avformat.h"
26 #include "internal.h"
27 #include "avio_internal.h"
28 
29 
30 
31 typedef struct MPJPEGDemuxContext {
32  const AVClass *class;
33  char *boundary;
34  char *searchstr;
38 
39 
40 static void trim_right(char *p)
41 {
42  char *end;
43 
44  if (!p || !*p)
45  return;
46 
47  end = p + strlen(p);
48  while (end > p && av_isspace(*(end-1)))
49  *(--end) = '\0';
50 }
51 
52 static int get_line(AVIOContext *pb, char *line, int line_size)
53 {
54  ff_get_line(pb, line, line_size);
55 
56  if (pb->error)
57  return pb->error;
58 
59  if (pb->eof_reached)
60  return AVERROR_EOF;
61 
62  trim_right(line);
63  return 0;
64 }
65 
66 
67 
68 static int split_tag_value(char **tag, char **value, char *line)
69 {
70  char *p = line;
71  int foundData = 0;
72 
73  *tag = NULL;
74  *value = NULL;
75 
76 
77  while (*p != '\0' && *p != ':') {
78  if (!av_isspace(*p)) {
79  foundData = 1;
80  }
81  p++;
82  }
83  if (*p != ':')
84  return foundData ? AVERROR_INVALIDDATA : 0;
85 
86  *p = '\0';
87  *tag = line;
88  trim_right(*tag);
89 
90  p++;
91 
92  while (av_isspace(*p))
93  p++;
94 
95  *value = p;
96  trim_right(*value);
97 
98  return 0;
99 }
100 
101 static int parse_multipart_header(AVIOContext *pb,
102  int* size,
103  const char* expected_boundary,
104  void *log_ctx);
105 
107 {
108  MPJPEGDemuxContext *mpjpeg = s->priv_data;
109  av_freep(&mpjpeg->boundary);
110  av_freep(&mpjpeg->searchstr);
111  return 0;
112 }
113 
114 static int mpjpeg_read_probe(const AVProbeData *p)
115 {
116  AVIOContext *pb;
117  int ret = 0;
118  int size = 0;
119 
120  if (p->buf_size < 2 || p->buf[0] != '-' || p->buf[1] != '-')
121  return 0;
122 
123  pb = avio_alloc_context(p->buf, p->buf_size, 0, NULL, NULL, NULL, NULL);
124  if (!pb)
125  return 0;
126 
127  ret = (parse_multipart_header(pb, &size, "--", NULL) >= 0) ? AVPROBE_SCORE_MAX : 0;
128 
129  avio_context_free(&pb);
130 
131  return ret;
132 }
133 
135 {
136  AVStream *st;
137  char boundary[70 + 2 + 1] = {0};
138  int64_t pos = avio_tell(s->pb);
139  int ret;
140 
141  do {
142  ret = get_line(s->pb, boundary, sizeof(boundary));
143  if (ret < 0)
144  return ret;
145  } while (!boundary[0]);
146 
147  if (strncmp(boundary, "--", 2))
148  return AVERROR_INVALIDDATA;
149 
150  st = avformat_new_stream(s, NULL);
151  if (!st)
152  return AVERROR(ENOMEM);
153 
156 
157  avpriv_set_pts_info(st, 60, 1, 25);
158 
159  avio_seek(s->pb, pos, SEEK_SET);
160 
161  return 0;
162 }
163 
164 static int parse_content_length(const char *value)
165 {
166  long int val = strtol(value, NULL, 10);
167 
168  if (val == LONG_MIN || val == LONG_MAX)
169  return AVERROR(errno);
170  if (val > INT_MAX)
171  return AVERROR(ERANGE);
172  return val;
173 }
174 
176  int* size,
177  const char* expected_boundary,
178  void *log_ctx)
179 {
180  char line[128];
181  int found_content_type = 0;
182  int ret;
183 
184  *size = -1;
185 
186  // get the CRLF as empty string
187  ret = get_line(pb, line, sizeof(line));
188  if (ret < 0)
189  return ret;
190 
191  /* some implementation do not provide the required
192  * initial CRLF (see rfc1341 7.2.1)
193  */
194  while (!line[0]) {
195  ret = get_line(pb, line, sizeof(line));
196  if (ret < 0)
197  return ret;
198  }
199 
200  if (!av_strstart(line, expected_boundary, NULL)) {
201  if (log_ctx)
202  av_log(log_ctx,
203  AV_LOG_ERROR,
204  "Expected boundary '%s' not found, instead found a line of %"SIZE_SPECIFIER" bytes\n",
205  expected_boundary,
206  strlen(line));
207 
208  return AVERROR_INVALIDDATA;
209  }
210 
211  while (!pb->eof_reached) {
212  char *tag, *value;
213 
214  ret = get_line(pb, line, sizeof(line));
215  if (ret < 0) {
216  if (ret == AVERROR_EOF)
217  break;
218  return ret;
219  }
220 
221  if (line[0] == '\0')
222  break;
223 
224  ret = split_tag_value(&tag, &value, line);
225  if (ret < 0)
226  return ret;
227  if (value==NULL || tag==NULL)
228  break;
229 
230  if (!av_strcasecmp(tag, "Content-type")) {
231  if (av_strcasecmp(value, "image/jpeg")) {
232  if (log_ctx)
233  av_log(log_ctx, AV_LOG_ERROR,
234  "Unexpected %s : %s\n",
235  tag, value);
236  return AVERROR_INVALIDDATA;
237  } else
238  found_content_type = 1;
239  } else if (!av_strcasecmp(tag, "Content-Length")) {
240  *size = parse_content_length(value);
241  if ( *size < 0 )
242  if (log_ctx)
243  av_log(log_ctx, AV_LOG_WARNING,
244  "Invalid Content-Length value : %s\n",
245  value);
246  }
247  }
248 
249  return found_content_type ? 0 : AVERROR_INVALIDDATA;
250 }
251 
252 
254 {
255  uint8_t *mime_type = NULL;
256  const char *start;
257  const char *end;
258  uint8_t *res = NULL;
259  int len;
260 
261  /* get MIME type, and skip to the first parameter */
262  av_opt_get(pb, "mime_type", AV_OPT_SEARCH_CHILDREN, &mime_type);
263  start = mime_type;
264  while (start != NULL && *start != '\0') {
265  start = strchr(start, ';');
266  if (!start)
267  break;
268 
269  start = start+1;
270 
271  while (av_isspace(*start))
272  start++;
273 
274  if (!av_stristart(start, "boundary=", &start)) {
275  end = strchr(start, ';');
276  if (end)
277  len = end - start - 1;
278  else
279  len = strlen(start);
280 
281  /* some endpoints may enclose the boundary
282  in Content-Type in quotes */
283  if ( len>2 && *start == '"' && start[len-1] == '"' ) {
284  start++;
285  len -= 2;
286  }
287  res = av_strndup(start, len);
288  break;
289  }
290  }
291 
292  av_freep(&mime_type);
293  return res;
294 }
295 
296 
298 {
299  int size;
300  int ret;
301 
302  MPJPEGDemuxContext *mpjpeg = s->priv_data;
303  if (mpjpeg->boundary == NULL) {
304  uint8_t* boundary = NULL;
305  if (mpjpeg->strict_mime_boundary) {
306  boundary = mpjpeg_get_boundary(s->pb);
307  }
308  if (boundary != NULL) {
309  mpjpeg->boundary = boundary;
310  mpjpeg->searchstr = av_asprintf( "\r\n%s\r\n", boundary );
311  } else {
312  mpjpeg->boundary = av_strdup("--");
313  mpjpeg->searchstr = av_strdup("\r\n--");
314  }
315  if (!mpjpeg->boundary || !mpjpeg->searchstr) {
316  av_freep(&mpjpeg->boundary);
317  av_freep(&mpjpeg->searchstr);
318  return AVERROR(ENOMEM);
319  }
320  mpjpeg->searchstr_len = strlen(mpjpeg->searchstr);
321  }
322 
323  ret = parse_multipart_header(s->pb, &size, mpjpeg->boundary, s);
324 
325 
326  if (ret < 0)
327  return ret;
328 
329  if (size > 0) {
330  /* size has been provided to us in MIME header */
331  ret = av_get_packet(s->pb, pkt, size);
332  } else {
333  /* no size was given -- we read until the next boundary or end-of-file */
334  int remaining = 0, len;
335 
336  const int read_chunk = 2048;
337  av_init_packet(pkt);
338  pkt->data = NULL;
339  pkt->size = 0;
340  pkt->pos = avio_tell(s->pb);
341 
342  /* we may need to return as much as all we've read back to the buffer */
343  ffio_ensure_seekback(s->pb, read_chunk);
344 
345  while ((ret = av_append_packet(s->pb, pkt, read_chunk - remaining)) >= 0) {
346  /* scan the new data */
347  char *start;
348 
349  len = ret + remaining;
350  start = pkt->data + pkt->size - len;
351  do {
352  if (!memcmp(start, mpjpeg->searchstr, mpjpeg->searchstr_len)) {
353  // got the boundary! rewind the stream
354  avio_seek(s->pb, -len, SEEK_CUR);
355  pkt->size -= len;
356  return pkt->size;
357  }
358  len--;
359  start++;
360  } while (len >= mpjpeg->searchstr_len);
361  remaining = len;
362  }
363 
364  /* error or EOF occurred */
365  if (ret == AVERROR_EOF) {
366  ret = pkt->size > 0 ? pkt->size : AVERROR_EOF;
367  } else {
368  av_packet_unref(pkt);
369  }
370  }
371 
372  return ret;
373 }
374 
375 #define OFFSET(x) offsetof(MPJPEGDemuxContext, x)
376 
377 #define DEC AV_OPT_FLAG_DECODING_PARAM
378 static const AVOption mpjpeg_options[] = {
379  { "strict_mime_boundary", "require MIME boundaries match", OFFSET(strict_mime_boundary), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC },
380  { NULL }
381 };
382 
383 
385  .class_name = "MPJPEG demuxer",
386  .item_name = av_default_item_name,
387  .option = mpjpeg_options,
388  .version = LIBAVUTIL_VERSION_INT,
389 };
390 
392  .name = "mpjpeg",
393  .long_name = NULL_IF_CONFIG_SMALL("MIME multipart JPEG"),
394  .mime_type = "multipart/x-mixed-replace",
395  .extensions = "mjpg",
396  .priv_data_size = sizeof(MPJPEGDemuxContext),
401  .priv_class = &mpjpeg_demuxer_class,
403 };
404 
405 
#define NULL
Definition: coverity.c:32
const char const char void * val
Definition: avisynth_c.h:863
Bytestream IO Context.
Definition: avio.h:161
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
AVOption.
Definition: opt.h:246
#define DEC
Definition: mpjpegdec.c:377
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
int64_t pos
byte position in stream, -1 if unknown
Definition: avcodec.h:1497
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:4892
static int get_line(AVIOContext *pb, char *line, int line_size)
Definition: mpjpegdec.c:52
static int read_chunk(AVFormatContext *s)
Definition: dhav.c:215
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3957
int size
Definition: avcodec.h:1478
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:246
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
static av_const int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
Definition: avstring.h:222
static int split_tag_value(char **tag, char **value, char *line)
Definition: mpjpegdec.c:68
static AVPacket pkt
Format I/O context.
Definition: avformat.h:1358
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
int av_stristart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str independent of case.
Definition: avstring.c:45
uint8_t
AVOptions.
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:108
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4465
uint8_t * data
Definition: avcodec.h:1477
uint32_t tag
Definition: movenc.c:1496
#define AVERROR_EOF
End of file.
Definition: error.h:55
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:145
int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
Allocate and read the payload of a packet and initialize its fields with default values.
Definition: utils.c:310
ptrdiff_t size
Definition: opengl_enc.c:100
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:557
static int mpjpeg_read_header(AVFormatContext *s)
Definition: mpjpegdec.c:134
#define av_log(a,...)
int av_append_packet(AVIOContext *s, AVPacket *pkt, int size)
Read data and append it to the current content of the AVPacket.
Definition: utils.c:320
AVIOContext * avio_alloc_context(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))
Allocate and initialize an AVIOContext for buffered I/O.
Definition: aviobuf.c:131
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
static int mpjpeg_read_close(AVFormatContext *s)
Definition: mpjpegdec.c:106
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3953
Definition: graph2dot.c:48
static const AVClass mpjpeg_demuxer_class
Definition: mpjpegdec.c:384
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:449
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:113
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:448
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:213
#define AV_OPT_SEARCH_CHILDREN
Search in possible children of the given object first.
Definition: opt.h:556
AVInputFormat ff_mpjpeg_demuxer
Definition: mpjpegdec.c:391
#define s(width, name)
Definition: cbs_vp9.c:257
int ff_get_line(AVIOContext *s, char *buf, int maxlen)
Read a whole line of text from AVIOContext.
Definition: aviobuf.c:811
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:530
Stream structure.
Definition: avformat.h:881
static int mpjpeg_read_probe(const AVProbeData *p)
Definition: mpjpegdec.c:114
static int parse_multipart_header(AVIOContext *pb, int *size, const char *expected_boundary, void *log_ctx)
Definition: mpjpegdec.c:175
#define AVFMT_NOTIMESTAMPS
Format does not need / have any timestamps.
Definition: avformat.h:467
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
AVIOContext * pb
I/O context.
Definition: avformat.h:1400
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:599
Describe the class of an AVClass context structure.
Definition: log.h:67
#define OFFSET(x)
Definition: mpjpegdec.c:375
int error
contains the error code or 0 if no error happened
Definition: avio.h:245
This structure contains the data a format has to probe a file.
Definition: avformat.h:446
#define SIZE_SPECIFIER
Definition: internal.h:262
#define flags(name, subs,...)
Definition: cbs_av1.c:561
static void trim_right(char *p)
Definition: mpjpegdec.c:40
int strict_mime_boundary
Definition: mpjpegdec.c:36
static int read_probe(const AVProbeData *pd)
Definition: jvdec.c:55
static const AVOption mpjpeg_options[]
Definition: mpjpegdec.c:378
int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size)
Ensures that the requested seekback buffer size will be available.
Definition: aviobuf.c:1054
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:458
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
Main libavformat public API header.
The official guide to swscale for confused that consecutive non overlapping rectangles of slice_bottom special converter These generally are unscaled converters of common like for each output line the vertical scaler pulls lines from a ring buffer When the ring buffer does not contain the wanted line
Definition: swscale.txt:33
void avio_context_free(AVIOContext **s)
Free the supplied IO context and everything associated with it.
Definition: aviobuf.c:148
void av_init_packet(AVPacket *pkt)
Initialize optional fields of a packet with default values.
Definition: avpacket.c:33
static int mpjpeg_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: mpjpegdec.c:297
int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
Definition: opt.c:761
int eof_reached
true if was unable to read due to error or eof
Definition: avio.h:239
int len
void * priv_data
Format private data.
Definition: avformat.h:1386
#define av_freep(p)
void INT64 start
Definition: avisynth_c.h:766
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:654
static char * mpjpeg_get_boundary(AVIOContext *pb)
Definition: mpjpegdec.c:253
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1028
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
static int parse_content_length(const char *value)
Definition: mpjpegdec.c:164
This structure stores compressed data.
Definition: avcodec.h:1454
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition: mem.c:263