Statistics
| Branch: | Revision:

ffmpeg / libav / jpeg.c @ 0726b2d1

History | View | Annotate | Download (6.2 KB)

1
/*
2
 * JPEG based formats
3
 * Copyright (c) 2000, 2001 Fabrice Bellard.
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with this library; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 */
19
#include "avformat.h"
20

    
21
/* Multipart JPEG */
22

    
23
#define BOUNDARY_TAG "ffserver"
24

    
25
static int mpjpeg_write_header(AVFormatContext *s)
26
{
27
    UINT8 buf1[256];
28

    
29
    snprintf(buf1, sizeof(buf1), "--%s\n", BOUNDARY_TAG);
30
    put_buffer(&s->pb, buf1, strlen(buf1));
31
    put_flush_packet(&s->pb);
32
    return 0;
33
}
34

    
35
static int mpjpeg_write_packet(AVFormatContext *s, int stream_index, 
36
                               UINT8 *buf, int size, int force_pts)
37
{
38
    UINT8 buf1[256];
39

    
40
    snprintf(buf1, sizeof(buf1), "Content-type: image/jpeg\n\n");
41
    put_buffer(&s->pb, buf1, strlen(buf1));
42
    put_buffer(&s->pb, buf, size);
43

    
44
    snprintf(buf1, sizeof(buf1), "\n--%s\n", BOUNDARY_TAG);
45
    put_buffer(&s->pb, buf1, strlen(buf1));
46
    put_flush_packet(&s->pb);
47
    return 0;
48
}
49

    
50
static int mpjpeg_write_trailer(AVFormatContext *s)
51
{
52
    return 0;
53
}
54

    
55
static AVOutputFormat mpjpeg_format = {
56
    "mpjpeg",
57
    "Mime multipart JPEG format",
58
    "multipart/x-mixed-replace;boundary=" BOUNDARY_TAG,
59
    "mjpg",
60
    0,
61
    CODEC_ID_NONE,
62
    CODEC_ID_MJPEG,
63
    mpjpeg_write_header,
64
    mpjpeg_write_packet,
65
    mpjpeg_write_trailer,
66
};
67

    
68

    
69
/*************************************/
70
/* single frame JPEG */
71

    
72
static int single_jpeg_write_header(AVFormatContext *s)
73
{
74
    return 0;
75
}
76

    
77
static int single_jpeg_write_packet(AVFormatContext *s, int stream_index,
78
                            UINT8 *buf, int size, int force_pts)
79
{
80
    put_buffer(&s->pb, buf, size);
81
    put_flush_packet(&s->pb);
82
    return 1; /* no more data can be sent */
83
}
84

    
85
static int single_jpeg_write_trailer(AVFormatContext *s)
86
{
87
    return 0;
88
}
89

    
90
static AVOutputFormat single_jpeg_format = {
91
    "singlejpeg",
92
    "single JPEG image",
93
    "image/jpeg",
94
    NULL, /* note: no extension to favorize jpeg multiple images match */
95
    0,
96
    CODEC_ID_NONE,
97
    CODEC_ID_MJPEG,
98
    single_jpeg_write_header,
99
    single_jpeg_write_packet,
100
    single_jpeg_write_trailer,
101
};
102

    
103
/*************************************/
104
/* multiple jpeg images */
105

    
106
typedef struct JpegContext {
107
    char path[1024];
108
    int img_number;
109
} JpegContext;
110

    
111
static int jpeg_write_header(AVFormatContext *s1)
112
{
113
    JpegContext *s;
114

    
115
    s = av_mallocz(sizeof(JpegContext));
116
    if (!s)
117
        return -1;
118
    s1->priv_data = s;
119
    pstrcpy(s->path, sizeof(s->path), s1->filename);
120
    s->img_number = 1;
121
    return 0;
122
}
123

    
124
static int jpeg_write_packet(AVFormatContext *s1, int stream_index,
125
                            UINT8 *buf, int size, int force_pts)
126
{
127
    JpegContext *s = s1->priv_data;
128
    char filename[1024];
129
    ByteIOContext f1, *pb = &f1;
130

    
131
    if (get_frame_filename(filename, sizeof(filename), 
132
                           s->path, s->img_number) < 0)
133
        return -EIO;
134
    if (url_fopen(pb, filename, URL_WRONLY) < 0)
135
        return -EIO;
136

    
137
    put_buffer(pb, buf, size);
138
    put_flush_packet(pb);
139

    
140
    url_fclose(pb);
141
    s->img_number++;
142

    
143
    return 0;
144
}
145

    
146
static int jpeg_write_trailer(AVFormatContext *s1)
147
{
148
    return 0;
149
}
150

    
151
/***/
152

    
153
static int jpeg_read_header(AVFormatContext *s1, AVFormatParameters *ap)
154
{
155
    JpegContext *s;
156
    int i;
157
    char buf[1024];
158
    ByteIOContext pb1, *f = &pb1;
159
    AVStream *st;
160

    
161
    s = av_mallocz(sizeof(JpegContext));
162
    if (!s)
163
        return -1;
164
    s1->priv_data = s;
165
    pstrcpy(s->path, sizeof(s->path), s1->filename);
166

    
167
    s1->nb_streams = 1;
168
    st = av_mallocz(sizeof(AVStream));
169
    if (!st) {
170
        av_free(s);
171
        return -ENOMEM;
172
    }
173
    s1->streams[0] = st;
174
    s->img_number = 0;
175

    
176
    /* try to find the first image */
177
    for(i=0;i<5;i++) {
178
        if (get_frame_filename(buf, sizeof(buf), s->path, s->img_number) < 0)
179
            goto fail;
180
        if (url_fopen(f, buf, URL_RDONLY) >= 0)
181
            break;
182
        s->img_number++;
183
    }
184
    if (i == 5)
185
        goto fail;
186
    url_fclose(f);
187
    st->codec.codec_type = CODEC_TYPE_VIDEO;
188
    st->codec.codec_id = CODEC_ID_MJPEG;
189
    
190
    if (!ap || !ap->frame_rate)
191
        st->codec.frame_rate = 25 * FRAME_RATE_BASE;
192
    else
193
        st->codec.frame_rate = ap->frame_rate;
194
    return 0;
195
 fail:
196
    av_free(s);
197
    return -EIO;
198
}
199

    
200
static int jpeg_read_packet(AVFormatContext *s1, AVPacket *pkt)
201
{
202
    JpegContext *s = s1->priv_data;
203
    char filename[1024];
204
    int size;
205
    ByteIOContext f1, *f = &f1;
206

    
207
    if (get_frame_filename(filename, sizeof(filename), 
208
                           s->path, s->img_number) < 0)
209
        return -EIO;
210
    
211
    f = &f1;
212
    if (url_fopen(f, filename, URL_RDONLY) < 0)
213
        return -EIO;
214
    
215
    size = url_seek(url_fileno(f), 0, SEEK_END);
216
    url_seek(url_fileno(f), 0, SEEK_SET);
217

    
218
    av_new_packet(pkt, size);
219
    pkt->stream_index = 0;
220
    get_buffer(f, pkt->data, size);
221

    
222
    url_fclose(f);
223
    s->img_number++;
224
    return 0;
225
}
226

    
227
static int jpeg_read_close(AVFormatContext *s1)
228
{
229
    return 0;
230
}
231

    
232
static AVInputFormat jpeg_iformat = {
233
    "jpeg",
234
    "JPEG image",
235
    sizeof(JpegContext),
236
    NULL,
237
    jpeg_read_header,
238
    jpeg_read_packet,
239
    jpeg_read_close,
240
    NULL,
241
    flags: AVFMT_NOFILE | AVFMT_NEEDNUMBER,
242
    extensions: "jpg,jpeg",
243
};
244

    
245
static AVOutputFormat jpeg_oformat = {
246
    "jpeg",
247
    "JPEG image",
248
    "image/jpeg",
249
    "jpg,jpeg",
250
    sizeof(JpegContext),
251
    CODEC_ID_NONE,
252
    CODEC_ID_MJPEG,
253
    jpeg_write_header,
254
    jpeg_write_packet,
255
    jpeg_write_trailer,
256
    flags: AVFMT_NOFILE | AVFMT_NEEDNUMBER,
257
};
258

    
259
int jpeg_init(void)
260
{
261
    av_register_output_format(&mpjpeg_format);
262
    av_register_output_format(&single_jpeg_format);
263
    av_register_input_format(&jpeg_iformat);
264
    av_register_output_format(&jpeg_oformat);
265
    return 0;
266
}