Libav
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 Libav.
6  *
7  * Libav 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  * Libav 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 Libav; 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 
24 #include "avformat.h"
25 #include "internal.h"
26 
27 static int get_line(AVIOContext *pb, char *line, int line_size)
28 {
29  int i = ff_get_line(pb, line, line_size);
30 
31  if (i > 1 && line[i - 2] == '\r')
32  line[i - 2] = '\0';
33 
34  if (pb->error)
35  return pb->error;
36 
37  if (pb->eof_reached)
38  return AVERROR_EOF;
39 
40  return 0;
41 }
42 
43 static int split_tag_value(char **tag, char **value, char *line)
44 {
45  char *p = line;
46 
47  while (*p != '\0' && *p != ':')
48  p++;
49  if (*p != ':')
50  return AVERROR_INVALIDDATA;
51 
52  *p = '\0';
53  *tag = line;
54 
55  p++;
56 
57  while (av_isspace(*p))
58  p++;
59 
60  *value = p;
61 
62  return 0;
63 }
64 
65 static int check_content_type(char *line)
66 {
67  char *tag, *value;
68  int ret = split_tag_value(&tag, &value, line);
69 
70  if (ret < 0)
71  return ret;
72 
73  if (av_strcasecmp(tag, "Content-type") ||
74  av_strcasecmp(value, "image/jpeg"))
75  return AVERROR_INVALIDDATA;
76 
77  return 0;
78 }
79 
81 {
82  AVIOContext *pb;
83  char line[128] = { 0 };
84  int ret = 0;
85 
86  if (p->buf_size < 2 || p->buf[0] != '-' || p->buf[1] != '-')
87  return 0;
88 
89  pb = avio_alloc_context(p->buf, p->buf_size, 0, NULL, NULL, NULL, NULL);
90  if (!pb)
91  return AVERROR(ENOMEM);
92 
93  while (!pb->eof_reached) {
94  ret = get_line(pb, line, sizeof(line));
95  if (ret < 0)
96  break;
97 
98  ret = check_content_type(line);
99  if (!ret) {
100  ret = AVPROBE_SCORE_MAX;
101  break;
102  }
103  }
104 
105  av_free(pb);
106 
107  return ret;
108 }
109 
111 {
112  AVStream *st;
113  char boundary[70 + 2 + 1];
114  int64_t pos = avio_tell(s->pb);
115  int ret;
116 
117 
118  ret = get_line(s->pb, boundary, sizeof(boundary));
119  if (ret < 0)
120  return ret;
121 
122  if (strncmp(boundary, "--", 2))
123  return AVERROR_INVALIDDATA;
124 
125  st = avformat_new_stream(s, NULL);
126  if (!st)
127  return AVERROR(ENOMEM);
128 
131 
132  avpriv_set_pts_info(st, 60, 1, 25);
133 
134  avio_seek(s->pb, pos, SEEK_SET);
135 
136  return 0;
137 }
138 
139 static int parse_content_length(const char *value)
140 {
141  long int val = strtol(value, NULL, 10);
142 
143  if (val == LONG_MIN || val == LONG_MAX)
144  return AVERROR(errno);
145  if (val > INT_MAX)
146  return AVERROR(ERANGE);
147  return val;
148 }
149 
151 {
152  char line[128];
153  int found_content_type = 0;
154  int ret, size = -1;
155 
156  // get the CRLF as empty string
157  ret = get_line(s->pb, line, sizeof(line));
158  if (ret < 0)
159  return ret;
160 
161  /* some implementation do not provide the required
162  * initial CRLF (see rfc1341 7.2.1)
163  */
164  if (!line[0]) {
165  ret = get_line(s->pb, line, sizeof(line));
166  if (ret < 0)
167  return ret;
168  }
169 
170  if (strncmp(line, "--", 2))
171  return AVERROR_INVALIDDATA;
172 
173  while (!s->pb->eof_reached) {
174  char *tag, *value;
175 
176  ret = get_line(s->pb, line, sizeof(line));
177  if (ret < 0)
178  return ret;
179 
180  if (line[0] == '\0')
181  break;
182 
183  ret = split_tag_value(&tag, &value, line);
184  if (ret < 0)
185  return ret;
186 
187  if (!av_strcasecmp(tag, "Content-type")) {
188  if (av_strcasecmp(value, "image/jpeg")) {
189  av_log(s, AV_LOG_ERROR,
190  "Unexpected %s : %s\n",
191  tag, value);
192  return AVERROR_INVALIDDATA;
193  } else
194  found_content_type = 1;
195  } else if (!av_strcasecmp(tag, "Content-Length")) {
196  size = parse_content_length(value);
197  if (size < 0)
198  return size;
199  }
200  }
201 
202  if (!found_content_type || size < 0) {
203  return AVERROR_INVALIDDATA;
204  }
205 
206  return size;
207 }
208 
210 {
211  int ret;
212  int size = parse_multipart_header(s);
213 
214  if (size < 0)
215  return size;
216 
217  ret = av_get_packet(s->pb, pkt, size);
218  if (ret < 0)
219  return ret;
220 
221  return 0;
222 }
223 
225  .name = "mpjpeg",
226  .long_name = NULL_IF_CONFIG_SMALL("MIME multipart JPEG"),
227  .mime_type = "multipart/x-mixed-replace",
228  .extensions = "mjpg",
229  .read_probe = mpjpeg_read_probe,
230  .read_header = mpjpeg_read_header,
231  .read_packet = mpjpeg_read_packet,
232 };
Bytestream IO Context.
Definition: avio.h:104
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:54
int size
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:2986
static int get_line(AVIOContext *pb, char *line, int line_size)
Definition: mpjpegdec.c:27
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3483
av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (%s)\, len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), use_generic ? ac->func_descr_generic :ac->func_descr)
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:242
static av_const int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
Definition: avstring.h:173
static int split_tag_value(char **tag, char **value, char *line)
Definition: mpjpegdec.c:43
Format I/O context.
Definition: avformat.h:940
static int parse_multipart_header(AVFormatContext *s)
Definition: mpjpegdec.c:150
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:2648
uint32_t tag
Definition: movenc.c:854
#define AVERROR_EOF
End of file.
Definition: error.h:51
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:117
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:295
static int mpjpeg_read_header(AVFormatContext *s)
Definition: mpjpegdec.c:110
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:151
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:124
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:190
#define AVERROR(e)
Definition: error.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:148
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3479
Definition: graph2dot.c:48
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:401
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:400
int av_strcasecmp(const char *a, const char *b)
Definition: avstring.c:156
AVInputFormat ff_mpjpeg_demuxer
Definition: mpjpegdec.c:224
static int mpjpeg_read_probe(AVProbeData *p)
Definition: mpjpegdec.c:80
int ff_get_line(AVIOContext *s, char *buf, int maxlen)
Read a whole line of text from AVIOContext.
Definition: aviobuf.c:704
Stream structure.
Definition: avformat.h:705
NULL
Definition: eval.c:55
AVIOContext * pb
I/O context.
Definition: avformat.h:982
static int check_content_type(char *line)
Definition: mpjpegdec.c:65
int error
contains the error code or 0 if no error happened
Definition: avio.h:138
This structure contains the data a format has to probe a file.
Definition: avformat.h:398
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:407
Main libavformat public API header.
static int mpjpeg_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: mpjpegdec.c:209
int eof_reached
true if eof reached
Definition: avio.h:132
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:529
AVCodecParameters * codecpar
Definition: avformat.h:831
static int parse_content_length(const char *value)
Definition: mpjpegdec.c:139
This structure stores compressed data.
Definition: avcodec.h:1323