Statistics
| Branch: | Revision:

ffmpeg / libavformat / img2.c @ c178fdea

History | View | Annotate | Download (13.6 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
    int split_planes;  /**< use independent file for each Y, U, V plane */
36
    char path[1024];
37
} VideoData;
38

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

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

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

    
95
static int infer_size(int *width_ptr, int *height_ptr, int size)
96
{
97
    int i;
98

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

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

    
118
        tags++;
119
    }
120
    return CODEC_ID_NONE;
121
}
122

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

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

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

    
176

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

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

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

    
198
    s1->ctx_flags |= AVFMTCTX_NOHEADER;
199

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

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

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

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

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

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

    
239
    if(s1->video_codec_id){
240
        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
241
        st->codec->codec_id = s1->video_codec_id;
242
    }else if(s1->audio_codec_id){
243
        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
244
        st->codec->codec_id = s1->audio_codec_id;
245
    }else{
246
        const char *str= strrchr(s->path, '.');
247
        s->split_planes = str && !strcasecmp(str + 1, "y");
248
        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
249
        st->codec->codec_id = av_str2id(img_tags, s->path);
250
    }
251
    if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ap->pix_fmt != PIX_FMT_NONE)
252
        st->codec->pix_fmt = ap->pix_fmt;
253

    
254
    return 0;
255
}
256

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

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

    
285
            if(!s->split_planes)
286
                break;
287
            filename[ strlen(filename) - 1 ]= 'U' + i;
288
        }
289

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

    
299
    av_new_packet(pkt, size[0] + size[1] + size[2]);
300
    pkt->stream_index = 0;
301
    pkt->flags |= AV_PKT_FLAG_KEY;
302

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

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

    
324
#if CONFIG_IMAGE2_MUXER || CONFIG_IMAGE2PIPE_MUXER
325
/******************************************************/
326
/* image output */
327

    
328
static int write_header(AVFormatContext *s)
329
{
330
    VideoData *img = s->priv_data;
331
    const char *str;
332

    
333
    img->img_number = 1;
334
    av_strlcpy(img->path, s->filename, sizeof(img->path));
335

    
336
    /* find format */
337
    if (s->oformat->flags & AVFMT_NOFILE)
338
        img->is_pipe = 0;
339
    else
340
        img->is_pipe = 1;
341

    
342
    str = strrchr(img->path, '.');
343
    img->split_planes = str && !strcasecmp(str + 1, "y");
344
    return 0;
345
}
346

    
347
static int write_packet(AVFormatContext *s, AVPacket *pkt)
348
{
349
    VideoData *img = s->priv_data;
350
    AVIOContext *pb[3];
351
    char filename[1024];
352
    AVCodecContext *codec= s->streams[ pkt->stream_index ]->codec;
353
    int i;
354

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

    
369
            if(!img->split_planes)
370
                break;
371
            filename[ strlen(filename) - 1 ]= 'U' + i;
372
        }
373
    } else {
374
        pb[0] = s->pb;
375
    }
376

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

    
417
    img->img_number++;
418
    return 0;
419
}
420

    
421
#endif /* CONFIG_IMAGE2_MUXER || CONFIG_IMAGE2PIPE_MUXER */
422

    
423
/* input */
424
#if CONFIG_IMAGE2_DEMUXER
425
AVInputFormat ff_image2_demuxer = {
426
    .name           = "image2",
427
    .long_name      = NULL_IF_CONFIG_SMALL("image2 sequence"),
428
    .priv_data_size = sizeof(VideoData),
429
    .read_probe     = read_probe,
430
    .read_header    = read_header,
431
    .read_packet    = read_packet,
432
    .flags          = AVFMT_NOFILE,
433
};
434
#endif
435
#if CONFIG_IMAGE2PIPE_DEMUXER
436
AVInputFormat ff_image2pipe_demuxer = {
437
    .name           = "image2pipe",
438
    .long_name      = NULL_IF_CONFIG_SMALL("piped image2 sequence"),
439
    .priv_data_size = sizeof(VideoData),
440
    .read_header    = read_header,
441
    .read_packet    = read_packet,
442
};
443
#endif
444

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