FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 
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  ret = get_line(s->pb, line, sizeof(line));
157  if (ret < 0)
158  return ret;
159 
160  if (strncmp(line, "--", 2))
161  return AVERROR_INVALIDDATA;
162 
163  while (!s->pb->eof_reached) {
164  char *tag, *value;
165 
166  ret = get_line(s->pb, line, sizeof(line));
167  if (ret < 0)
168  return ret;
169 
170  if (line[0] == '\0')
171  break;
172 
173  ret = split_tag_value(&tag, &value, line);
174  if (ret < 0)
175  return ret;
176 
177  if (!av_strcasecmp(tag, "Content-type")) {
178  if (av_strcasecmp(value, "image/jpeg")) {
179  av_log(s, AV_LOG_ERROR,
180  "Unexpected %s : %s\n",
181  tag, value);
182  return AVERROR_INVALIDDATA;
183  } else
184  found_content_type = 1;
185  } else if (!av_strcasecmp(tag, "Content-Length")) {
186  size = parse_content_length(value);
187  if (size < 0)
188  return size;
189  }
190  }
191 
192  if (!found_content_type || size < 0) {
193  return AVERROR_INVALIDDATA;
194  }
195 
196  return size;
197 }
198 
200 {
201  int ret;
202  int size = parse_multipart_header(s);
203 
204  if (size < 0)
205  return size;
206 
207  ret = av_get_packet(s->pb, pkt, size);
208  if (ret < 0)
209  return ret;
210 
211  // trailing empty line
212  avio_skip(s->pb, 2);
213 
214  return 0;
215 }
216 
218  .name = "mpjpeg",
219  .long_name = NULL_IF_CONFIG_SMALL("MIME multipart JPEG"),
220  .mime_type = "multipart/x-mixed-replace",
221  .extensions = "mjpg",
222  .read_probe = mpjpeg_read_probe,
223  .read_header = mpjpeg_read_header,
224  .read_packet = mpjpeg_read_packet,
225 };
#define NULL
Definition: coverity.c:32
const char const char void * val
Definition: avisynth_c.h:634
const char * s
Definition: avisynth_c.h:631
Bytestream IO Context.
Definition: avio.h:111
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
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:4083
static int get_line(AVIOContext *pb, char *line, int line_size)
Definition: mpjpegdec.c:27
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:204
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:277
static int split_tag_value(char **tag, char **value, char *line)
Definition: mpjpegdec.c:43
static AVPacket pkt
Format I/O context.
Definition: avformat.h:1273
int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
Definition: avstring.c:330
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:3749
uint32_t tag
Definition: movenc.c:1334
#define AVERROR_EOF
End of file.
Definition: error.h:55
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:244
ptrdiff_t size
Definition: opengl_enc.c:101
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:390
static int mpjpeg_read_header(AVFormatContext *s)
Definition: mpjpegdec.c:110
#define av_log(a,...)
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:112
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
#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:175
Definition: graph2dot.c:48
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:861
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:451
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:450
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:213
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:109
AVInputFormat ff_mpjpeg_demuxer
Definition: mpjpegdec.c:217
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:698
Stream structure.
Definition: avformat.h:842
enum AVMediaType codec_type
Definition: avcodec.h:1510
enum AVCodecID codec_id
Definition: avcodec.h:1519
AVIOContext * pb
I/O context.
Definition: avformat.h:1315
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:145
This structure contains the data a format has to probe a file.
Definition: avformat.h:448
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:460
Main libavformat public API header.
static int mpjpeg_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: mpjpegdec.c:199
#define av_free(p)
int eof_reached
true if eof reached
Definition: avio.h:139
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:628
static int parse_content_length(const char *value)
Definition: mpjpegdec.c:139
This structure stores compressed data.
Definition: avcodec.h:1400