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 
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 
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")) {
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;
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 */
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 {
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 
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:599
MPJPEGDemuxContext::boundary
char * boundary
Definition: mpjpegdec.c:33
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
AVERROR
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
opt.h
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4480
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3953
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:55
avio_context_free
void avio_context_free(AVIOContext **s)
Free the supplied IO context and everything associated with it.
Definition: aviobuf.c:148
AVFMT_NOTIMESTAMPS
#define AVFMT_NOTIMESTAMPS
Format does not need / have any timestamps.
Definition: avformat.h:467
av_asprintf
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:113
av_strcasecmp
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:213
av_isspace
static av_const int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
Definition: avstring.h:222
end
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
AVPacket::data
uint8_t * data
Definition: avcodec.h:1477
AVOption
AVOption.
Definition: opt.h:246
AVIOContext::error
int error
contains the error code or 0 if no error happened
Definition: avio.h:245
AVProbeData::buf_size
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:449
DEC
#define DEC
Definition: mpjpegdec.c:377
AVPROBE_SCORE_MAX
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:458
start
void INT64 start
Definition: avisynth_c.h:767
read_close
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:145
avio_tell
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:557
OFFSET
#define OFFSET(x)
Definition: mpjpegdec.c:375
get_line
static int get_line(AVIOContext *pb, char *line, int line_size)
Definition: mpjpegdec.c:52
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
AVInputFormat
Definition: avformat.h:640
mpjpeg_get_boundary
static char * mpjpeg_get_boundary(AVIOContext *pb)
Definition: mpjpegdec.c:253
s
#define s(width, name)
Definition: cbs_vp9.c:257
trim_right
static void trim_right(char *p)
Definition: mpjpegdec.c:40
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:645
AVProbeData::buf
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:448
read_chunk
static int read_chunk(AVFormatContext *s)
Definition: dhav.c:215
av_stristart
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
parse_multipart_header
static int parse_multipart_header(AVIOContext *pb, int *size, const char *expected_boundary, void *log_ctx)
Definition: mpjpegdec.c:175
MPJPEGDemuxContext::searchstr
char * searchstr
Definition: mpjpegdec.c:34
AVFormatContext
Format I/O context.
Definition: avformat.h:1342
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1017
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
read_header
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:530
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:67
NULL
#define NULL
Definition: coverity.c:32
read_probe
static int read_probe(const AVProbeData *pd)
Definition: jvdec.c:55
MPJPEGDemuxContext::searchstr_len
int searchstr_len
Definition: mpjpegdec.c:35
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
AVProbeData
This structure contains the data a format has to probe a file.
Definition: avformat.h:446
mpjpeg_demuxer_class
static const AVClass mpjpeg_demuxer_class
Definition: mpjpegdec.c:384
AVIOContext
Bytestream IO Context.
Definition: avio.h:161
AVPacket::size
int size
Definition: avcodec.h:1478
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:188
MPJPEGDemuxContext::strict_mime_boundary
int strict_mime_boundary
Definition: mpjpegdec.c:36
avpriv_set_pts_info
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:4910
size
int size
Definition: twinvq_data.h:11134
val
const char const char void * val
Definition: avisynth_c.h:863
AV_OPT_SEARCH_CHILDREN
#define AV_OPT_SEARCH_CHILDREN
Search in possible children of the given object first.
Definition: opt.h:556
ffio_ensure_seekback
int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size)
Ensures that the requested seekback buffer size will be available.
Definition: aviobuf.c:1051
mpjpeg_read_probe
static int mpjpeg_read_probe(const AVProbeData *p)
Definition: mpjpegdec.c:114
line
Definition: graph2dot.c:48
mpjpeg_read_close
static int mpjpeg_read_close(AVFormatContext *s)
Definition: mpjpegdec.c:106
mpjpeg_read_packet
static int mpjpeg_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: mpjpegdec.c:297
mpjpeg_options
static const AVOption mpjpeg_options[]
Definition: mpjpegdec.c:378
av_strstart
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
MPJPEGDemuxContext
Definition: mpjpegdec.c:31
AV_CODEC_ID_MJPEG
@ AV_CODEC_ID_MJPEG
Definition: avcodec.h:225
avio_internal.h
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
avio_alloc_context
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
uint8_t
uint8_t
Definition: audio_convert.c:194
ff_get_line
int ff_get_line(AVIOContext *s, char *buf, int maxlen)
Read a whole line of text from AVIOContext.
Definition: aviobuf.c:808
len
int len
Definition: vorbis_enc_data.h:452
split_tag_value
static int split_tag_value(char **tag, char **value, char *line)
Definition: mpjpegdec.c:68
parse_content_length
static int parse_content_length(const char *value)
Definition: mpjpegdec.c:164
av_get_packet
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:313
tag
uint32_t tag
Definition: movenc.c:1496
ret
ret
Definition: filter_design.txt:187
read_packet
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
AVStream
Stream structure.
Definition: avformat.h:870
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:246
AVClass::class_name
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
av_append_packet
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:323
avformat.h
SIZE_SPECIFIER
#define SIZE_SPECIFIER
Definition: internal.h:264
pkt
static AVPacket pkt
Definition: demuxing_decoding.c:54
AVIOContext::eof_reached
int eof_reached
true if was unable to read due to error or eof
Definition: avio.h:239
mpjpeg_read_header
static int mpjpeg_read_header(AVFormatContext *s)
Definition: mpjpegdec.c:134
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
ff_mpjpeg_demuxer
AVInputFormat ff_mpjpeg_demuxer
Definition: mpjpegdec.c:391
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3957
AVPacket
This structure stores compressed data.
Definition: avcodec.h:1454
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:240
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
AVPacket::pos
int64_t pos
byte position in stream, -1 if unknown
Definition: avcodec.h:1497
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:565
av_opt_get
int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
Definition: opt.c:761
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
avstring.h
av_strndup
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition: mem.c:263
line
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:40
av_init_packet
void av_init_packet(AVPacket *pkt)
Initialize optional fields of a packet with default values.
Definition: avpacket.c:33