Statistics
| Branch: | Revision:

ffmpeg / libavformat / img2.c @ 32442930

History | View | Annotate | Download (13.3 KB)

1
/*
2
 * Image format
3
 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4
 * Copyright (c) 2004 Michael Niedermayer
5
 *
6
 * This file is part of FFmpeg.
7
 *
8
 * FFmpeg is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * FFmpeg is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with FFmpeg; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
 */
22

    
23
#include "libavutil/intreadwrite.h"
24
#include "libavutil/avstring.h"
25
#include "avformat.h"
26
#include "avio_internal.h"
27
#include <strings.h>
28

    
29
typedef struct {
30
    int img_first;
31
    int img_last;
32
    int img_number;
33
    int img_count;
34
    int is_pipe;
35
    char path[1024];
36
} VideoData;
37

    
38
typedef struct {
39
    enum CodecID id;
40
    const char *str;
41
} IdStrMap;
42

    
43
static const IdStrMap img_tags[] = {
44
    { CODEC_ID_MJPEG     , "jpeg"},
45
    { CODEC_ID_MJPEG     , "jpg"},
46
    { CODEC_ID_LJPEG     , "ljpg"},
47
    { CODEC_ID_PNG       , "png"},
48
    { CODEC_ID_PNG       , "mng"},
49
    { CODEC_ID_PPM       , "ppm"},
50
    { CODEC_ID_PPM       , "pnm"},
51
    { CODEC_ID_PGM       , "pgm"},
52
    { CODEC_ID_PGMYUV    , "pgmyuv"},
53
    { CODEC_ID_PBM       , "pbm"},
54
    { CODEC_ID_PAM       , "pam"},
55
    { CODEC_ID_MPEG1VIDEO, "mpg1-img"},
56
    { CODEC_ID_MPEG2VIDEO, "mpg2-img"},
57
    { CODEC_ID_MPEG4     , "mpg4-img"},
58
    { CODEC_ID_FFV1      , "ffv1-img"},
59
    { CODEC_ID_RAWVIDEO  , "y"},
60
    { CODEC_ID_BMP       , "bmp"},
61
    { CODEC_ID_GIF       , "gif"},
62
    { CODEC_ID_TARGA     , "tga"},
63
    { CODEC_ID_TIFF      , "tiff"},
64
    { CODEC_ID_TIFF      , "tif"},
65
    { CODEC_ID_SGI       , "sgi"},
66
    { CODEC_ID_PTX       , "ptx"},
67
    { CODEC_ID_PCX       , "pcx"},
68
    { CODEC_ID_SUNRAST   , "sun"},
69
    { CODEC_ID_SUNRAST   , "ras"},
70
    { CODEC_ID_SUNRAST   , "rs"},
71
    { CODEC_ID_SUNRAST   , "im1"},
72
    { CODEC_ID_SUNRAST   , "im8"},
73
    { CODEC_ID_SUNRAST   , "im24"},
74
    { CODEC_ID_SUNRAST   , "sunras"},
75
    { CODEC_ID_JPEG2000  , "jp2"},
76
    { CODEC_ID_DPX       , "dpx"},
77
    { CODEC_ID_PICTOR    , "pic"},
78
    { CODEC_ID_NONE      , NULL}
79
};
80

    
81
static const int sizes[][2] = {
82
    { 640, 480 },
83
    { 720, 480 },
84
    { 720, 576 },
85
    { 352, 288 },
86
    { 352, 240 },
87
    { 160, 128 },
88
    { 512, 384 },
89
    { 640, 352 },
90
    { 640, 240 },
91
};
92

    
93
static int infer_size(int *width_ptr, int *height_ptr, int size)
94
{
95
    int i;
96

    
97
    for(i=0;i<FF_ARRAY_ELEMS(sizes);i++) {
98
        if ((sizes[i][0] * sizes[i][1]) == size) {
99
            *width_ptr = sizes[i][0];
100
            *height_ptr = sizes[i][1];
101
            return 0;
102
        }
103
    }
104
    return -1;
105
}
106
static enum CodecID av_str2id(const IdStrMap *tags, const char *str)
107
{
108
    str= strrchr(str, '.');
109
    if(!str) return CODEC_ID_NONE;
110
    str++;
111

    
112
    while (tags->id) {
113
        if (!strcasecmp(str, tags->str))
114
            return tags->id;
115

    
116
        tags++;
117
    }
118
    return CODEC_ID_NONE;
119
}
120

    
121
/* return -1 if no image found */
122
static int find_image_range(int *pfirst_index, int *plast_index,
123
                            const char *path)
124
{
125
    char buf[1024];
126
    int range, last_index, range1, first_index;
127

    
128
    /* find the first image */
129
    for(first_index = 0; first_index < 5; first_index++) {
130
        if (av_get_frame_filename(buf, sizeof(buf), path, first_index) < 0){
131
            *pfirst_index =
132
            *plast_index = 1;
133
            if(url_exist(buf))
134
                return 0;
135
            return -1;
136
        }
137
        if (url_exist(buf))
138
            break;
139
    }
140
    if (first_index == 5)
141
        goto fail;
142

    
143
    /* find the last image */
144
    last_index = first_index;
145
    for(;;) {
146
        range = 0;
147
        for(;;) {
148
            if (!range)
149
                range1 = 1;
150
            else
151
                range1 = 2 * range;
152
            if (av_get_frame_filename(buf, sizeof(buf), path,
153
                                      last_index + range1) < 0)
154
                goto fail;
155
            if (!url_exist(buf))
156
                break;
157
            range = range1;
158
            /* just in case... */
159
            if (range >= (1 << 30))
160
                goto fail;
161
        }
162
        /* we are sure than image last_index + range exists */
163
        if (!range)
164
            break;
165
        last_index += range;
166
    }
167
    *pfirst_index = first_index;
168
    *plast_index = last_index;
169
    return 0;
170
 fail:
171
    return -1;
172
}
173

    
174

    
175
static int read_probe(AVProbeData *p)
176
{
177
    if (p->filename && av_str2id(img_tags, p->filename)) {
178
        if (av_filename_number_test(p->filename))
179
            return AVPROBE_SCORE_MAX;
180
        else
181
            return AVPROBE_SCORE_MAX/2;
182
    }
183
    return 0;
184
}
185

    
186
enum CodecID av_guess_image2_codec(const char *filename){
187
    return av_str2id(img_tags, filename);
188
}
189

    
190
static int read_header(AVFormatContext *s1, AVFormatParameters *ap)
191
{
192
    VideoData *s = s1->priv_data;
193
    int first_index, last_index;
194
    AVStream *st;
195

    
196
    s1->ctx_flags |= AVFMTCTX_NOHEADER;
197

    
198
    st = av_new_stream(s1, 0);
199
    if (!st) {
200
        return AVERROR(ENOMEM);
201
    }
202

    
203
    av_strlcpy(s->path, s1->filename, sizeof(s->path));
204
    s->img_number = 0;
205
    s->img_count = 0;
206

    
207
    /* find format */
208
    if (s1->iformat->flags & AVFMT_NOFILE)
209
        s->is_pipe = 0;
210
    else{
211
        s->is_pipe = 1;
212
        st->need_parsing = AVSTREAM_PARSE_FULL;
213
    }
214

    
215
    if (!ap->time_base.num) {
216
        av_set_pts_info(st, 60, 1, 25);
217
    } else {
218
        av_set_pts_info(st, 60, ap->time_base.num, ap->time_base.den);
219
    }
220

    
221
    if(ap->width && ap->height){
222
        st->codec->width = ap->width;
223
        st->codec->height= ap->height;
224
    }
225

    
226
    if (!s->is_pipe) {
227
        if (find_image_range(&first_index, &last_index, s->path) < 0)
228
            return AVERROR(ENOENT);
229
        s->img_first = first_index;
230
        s->img_last = last_index;
231
        s->img_number = first_index;
232
        /* compute duration */
233
        st->start_time = 0;
234
        st->duration = last_index - first_index + 1;
235
    }
236

    
237
    if(s1->video_codec_id){
238
        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
239
        st->codec->codec_id = s1->video_codec_id;
240
    }else if(s1->audio_codec_id){
241
        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
242
        st->codec->codec_id = s1->audio_codec_id;
243
    }else{
244
        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
245
        st->codec->codec_id = av_str2id(img_tags, s->path);
246
    }
247
    if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ap->pix_fmt != PIX_FMT_NONE)
248
        st->codec->pix_fmt = ap->pix_fmt;
249

    
250
    return 0;
251
}
252

    
253
static int read_packet(AVFormatContext *s1, AVPacket *pkt)
254
{
255
    VideoData *s = s1->priv_data;
256
    char filename[1024];
257
    int i;
258
    int size[3]={0}, ret[3]={0};
259
    AVIOContext *f[3];
260
    AVCodecContext *codec= s1->streams[0]->codec;
261

    
262
    if (!s->is_pipe) {
263
        /* loop over input */
264
        if (s1->loop_input && s->img_number > s->img_last) {
265
            s->img_number = s->img_first;
266
        }
267
        if (s->img_number > s->img_last)
268
            return AVERROR_EOF;
269
        if (av_get_frame_filename(filename, sizeof(filename),
270
                                  s->path, s->img_number)<0 && s->img_number > 1)
271
            return AVERROR(EIO);
272
        for(i=0; i<3; i++){
273
            if (avio_open(&f[i], filename, URL_RDONLY) < 0) {
274
                if(i==1)
275
                    break;
276
                av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n",filename);
277
                return AVERROR(EIO);
278
            }
279
            size[i]= url_fsize(f[i]);
280

    
281
            if(codec->codec_id != CODEC_ID_RAWVIDEO)
282
                break;
283
            filename[ strlen(filename) - 1 ]= 'U' + i;
284
        }
285

    
286
        if(codec->codec_id == CODEC_ID_RAWVIDEO && !codec->width)
287
            infer_size(&codec->width, &codec->height, size[0]);
288
    } else {
289
        f[0] = s1->pb;
290
        if (url_feof(f[0]))
291
            return AVERROR(EIO);
292
        size[0]= 4096;
293
    }
294

    
295
    av_new_packet(pkt, size[0] + size[1] + size[2]);
296
    pkt->stream_index = 0;
297
    pkt->flags |= AV_PKT_FLAG_KEY;
298

    
299
    pkt->size= 0;
300
    for(i=0; i<3; i++){
301
        if(size[i]){
302
            ret[i]= avio_read(f[i], pkt->data + pkt->size, size[i]);
303
            if (!s->is_pipe)
304
                avio_close(f[i]);
305
            if(ret[i]>0)
306
                pkt->size += ret[i];
307
        }
308
    }
309

    
310
    if (ret[0] <= 0 || ret[1]<0 || ret[2]<0) {
311
        av_free_packet(pkt);
312
        return AVERROR(EIO); /* signal EOF */
313
    } else {
314
        s->img_count++;
315
        s->img_number++;
316
        return 0;
317
    }
318
}
319

    
320
#if CONFIG_IMAGE2_MUXER || CONFIG_IMAGE2PIPE_MUXER
321
/******************************************************/
322
/* image output */
323

    
324
static int write_header(AVFormatContext *s)
325
{
326
    VideoData *img = s->priv_data;
327

    
328
    img->img_number = 1;
329
    av_strlcpy(img->path, s->filename, sizeof(img->path));
330

    
331
    /* find format */
332
    if (s->oformat->flags & AVFMT_NOFILE)
333
        img->is_pipe = 0;
334
    else
335
        img->is_pipe = 1;
336

    
337
    return 0;
338
}
339

    
340
static int write_packet(AVFormatContext *s, AVPacket *pkt)
341
{
342
    VideoData *img = s->priv_data;
343
    AVIOContext *pb[3];
344
    char filename[1024];
345
    AVCodecContext *codec= s->streams[ pkt->stream_index ]->codec;
346
    int i;
347

    
348
    if (!img->is_pipe) {
349
        if (av_get_frame_filename(filename, sizeof(filename),
350
                                  img->path, img->img_number) < 0 && img->img_number>1) {
351
            av_log(s, AV_LOG_ERROR,
352
                   "Could not get frame filename number %d from pattern '%s'\n",
353
                   img->img_number, img->path);
354
            return AVERROR(EIO);
355
        }
356
        for(i=0; i<3; i++){
357
            if (avio_open(&pb[i], filename, URL_WRONLY) < 0) {
358
                av_log(s, AV_LOG_ERROR, "Could not open file : %s\n",filename);
359
                return AVERROR(EIO);
360
            }
361

    
362
            if(codec->codec_id != CODEC_ID_RAWVIDEO)
363
                break;
364
            filename[ strlen(filename) - 1 ]= 'U' + i;
365
        }
366
    } else {
367
        pb[0] = s->pb;
368
    }
369

    
370
    if(codec->codec_id == CODEC_ID_RAWVIDEO){
371
        int ysize = codec->width * codec->height;
372
        avio_write(pb[0], pkt->data        , ysize);
373
        avio_write(pb[1], pkt->data + ysize, (pkt->size - ysize)/2);
374
        avio_write(pb[2], pkt->data + ysize +(pkt->size - ysize)/2, (pkt->size - ysize)/2);
375
        put_flush_packet(pb[1]);
376
        put_flush_packet(pb[2]);
377
        avio_close(pb[1]);
378
        avio_close(pb[2]);
379
    }else{
380
        if(av_str2id(img_tags, s->filename) == CODEC_ID_JPEG2000){
381
            AVStream *st = s->streams[0];
382
            if(st->codec->extradata_size > 8 &&
383
               AV_RL32(st->codec->extradata+4) == MKTAG('j','p','2','h')){
384
                if(pkt->size < 8 || AV_RL32(pkt->data+4) != MKTAG('j','p','2','c'))
385
                    goto error;
386
                avio_wb32(pb[0], 12);
387
                ffio_wfourcc(pb[0], "jP  ");
388
                avio_wb32(pb[0], 0x0D0A870A); // signature
389
                avio_wb32(pb[0], 20);
390
                ffio_wfourcc(pb[0], "ftyp");
391
                ffio_wfourcc(pb[0], "jp2 ");
392
                avio_wb32(pb[0], 0);
393
                ffio_wfourcc(pb[0], "jp2 ");
394
                avio_write(pb[0], st->codec->extradata, st->codec->extradata_size);
395
            }else if(pkt->size < 8 ||
396
                     (!st->codec->extradata_size &&
397
                      AV_RL32(pkt->data+4) != MKTAG('j','P',' ',' '))){ // signature
398
            error:
399
                av_log(s, AV_LOG_ERROR, "malformated jpeg2000 codestream\n");
400
                return -1;
401
            }
402
        }
403
        avio_write(pb[0], pkt->data, pkt->size);
404
    }
405
    put_flush_packet(pb[0]);
406
    if (!img->is_pipe) {
407
        avio_close(pb[0]);
408
    }
409

    
410
    img->img_number++;
411
    return 0;
412
}
413

    
414
#endif /* CONFIG_IMAGE2_MUXER || CONFIG_IMAGE2PIPE_MUXER */
415

    
416
/* input */
417
#if CONFIG_IMAGE2_DEMUXER
418
AVInputFormat ff_image2_demuxer = {
419
    .name           = "image2",
420
    .long_name      = NULL_IF_CONFIG_SMALL("image2 sequence"),
421
    .priv_data_size = sizeof(VideoData),
422
    .read_probe     = read_probe,
423
    .read_header    = read_header,
424
    .read_packet    = read_packet,
425
    .flags          = AVFMT_NOFILE,
426
};
427
#endif
428
#if CONFIG_IMAGE2PIPE_DEMUXER
429
AVInputFormat ff_image2pipe_demuxer = {
430
    .name           = "image2pipe",
431
    .long_name      = NULL_IF_CONFIG_SMALL("piped image2 sequence"),
432
    .priv_data_size = sizeof(VideoData),
433
    .read_header    = read_header,
434
    .read_packet    = read_packet,
435
};
436
#endif
437

    
438
/* output */
439
#if CONFIG_IMAGE2_MUXER
440
AVOutputFormat ff_image2_muxer = {
441
    .name           = "image2",
442
    .long_name      = NULL_IF_CONFIG_SMALL("image2 sequence"),
443
    .extensions     = "bmp,jpeg,jpg,ljpg,pam,pbm,pcx,pgm,pgmyuv,png,"
444
                      "ppm,sgi,tga,tif,tiff,jp2",
445
    .priv_data_size = sizeof(VideoData),
446
    .video_codec    = CODEC_ID_MJPEG,
447
    .write_header   = write_header,
448
    .write_packet   = write_packet,
449
    .flags          = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS | AVFMT_NOFILE
450
};
451
#endif
452
#if CONFIG_IMAGE2PIPE_MUXER
453
AVOutputFormat ff_image2pipe_muxer = {
454
    .name           = "image2pipe",
455
    .long_name      = NULL_IF_CONFIG_SMALL("piped image2 sequence"),
456
    .priv_data_size = sizeof(VideoData),
457
    .video_codec    = CODEC_ID_MJPEG,
458
    .write_header   = write_header,
459
    .write_packet   = write_packet,
460
    .flags          = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS
461
};
462
#endif