libavformat/img2.c
Go to the documentation of this file.
00001 /*
00002  * Image format
00003  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
00004  * Copyright (c) 2004 Michael Niedermayer
00005  *
00006  * This file is part of Libav.
00007  *
00008  * Libav is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * Libav is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with Libav; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00021  */
00022 
00023 #include "libavutil/intreadwrite.h"
00024 #include "libavutil/avstring.h"
00025 #include "libavutil/log.h"
00026 #include "libavutil/opt.h"
00027 #include "libavutil/pixdesc.h"
00028 #include "libavutil/parseutils.h"
00029 #include "avformat.h"
00030 #include "avio_internal.h"
00031 #include "internal.h"
00032 
00033 typedef struct {
00034     const AVClass *class;  
00035     int img_first;
00036     int img_last;
00037     int img_number;
00038     int img_count;
00039     int is_pipe;
00040     char path[1024];
00041     char *pixel_format;     
00042     char *video_size;       
00043     char *framerate;        
00044     int loop;
00045 } VideoData;
00046 
00047 typedef struct {
00048     enum CodecID id;
00049     const char *str;
00050 } IdStrMap;
00051 
00052 static const IdStrMap img_tags[] = {
00053     { CODEC_ID_MJPEG     , "jpeg"},
00054     { CODEC_ID_MJPEG     , "jpg"},
00055     { CODEC_ID_LJPEG     , "ljpg"},
00056     { CODEC_ID_PNG       , "png"},
00057     { CODEC_ID_PNG       , "mng"},
00058     { CODEC_ID_PPM       , "ppm"},
00059     { CODEC_ID_PPM       , "pnm"},
00060     { CODEC_ID_PGM       , "pgm"},
00061     { CODEC_ID_PGMYUV    , "pgmyuv"},
00062     { CODEC_ID_PBM       , "pbm"},
00063     { CODEC_ID_PAM       , "pam"},
00064     { CODEC_ID_MPEG1VIDEO, "mpg1-img"},
00065     { CODEC_ID_MPEG2VIDEO, "mpg2-img"},
00066     { CODEC_ID_MPEG4     , "mpg4-img"},
00067     { CODEC_ID_FFV1      , "ffv1-img"},
00068     { CODEC_ID_RAWVIDEO  , "y"},
00069     { CODEC_ID_BMP       , "bmp"},
00070     { CODEC_ID_GIF       , "gif"},
00071     { CODEC_ID_TARGA     , "tga"},
00072     { CODEC_ID_TIFF      , "tiff"},
00073     { CODEC_ID_TIFF      , "tif"},
00074     { CODEC_ID_SGI       , "sgi"},
00075     { CODEC_ID_PTX       , "ptx"},
00076     { CODEC_ID_PCX       , "pcx"},
00077     { CODEC_ID_SUNRAST   , "sun"},
00078     { CODEC_ID_SUNRAST   , "ras"},
00079     { CODEC_ID_SUNRAST   , "rs"},
00080     { CODEC_ID_SUNRAST   , "im1"},
00081     { CODEC_ID_SUNRAST   , "im8"},
00082     { CODEC_ID_SUNRAST   , "im24"},
00083     { CODEC_ID_SUNRAST   , "sunras"},
00084     { CODEC_ID_JPEG2000  , "jp2"},
00085     { CODEC_ID_JPEG2000  , "jpc"},
00086     { CODEC_ID_DPX       , "dpx"},
00087     { CODEC_ID_PICTOR    , "pic"},
00088     { CODEC_ID_NONE      , NULL}
00089 };
00090 
00091 static const int sizes[][2] = {
00092     { 640, 480 },
00093     { 720, 480 },
00094     { 720, 576 },
00095     { 352, 288 },
00096     { 352, 240 },
00097     { 160, 128 },
00098     { 512, 384 },
00099     { 640, 352 },
00100     { 640, 240 },
00101 };
00102 
00103 static int infer_size(int *width_ptr, int *height_ptr, int size)
00104 {
00105     int i;
00106 
00107     for(i=0;i<FF_ARRAY_ELEMS(sizes);i++) {
00108         if ((sizes[i][0] * sizes[i][1]) == size) {
00109             *width_ptr = sizes[i][0];
00110             *height_ptr = sizes[i][1];
00111             return 0;
00112         }
00113     }
00114     return -1;
00115 }
00116 static enum CodecID av_str2id(const IdStrMap *tags, const char *str)
00117 {
00118     str= strrchr(str, '.');
00119     if(!str) return CODEC_ID_NONE;
00120     str++;
00121 
00122     while (tags->id) {
00123         if (!av_strcasecmp(str, tags->str))
00124             return tags->id;
00125 
00126         tags++;
00127     }
00128     return CODEC_ID_NONE;
00129 }
00130 
00131 /* return -1 if no image found */
00132 static int find_image_range(int *pfirst_index, int *plast_index,
00133                             const char *path)
00134 {
00135     char buf[1024];
00136     int range, last_index, range1, first_index;
00137 
00138     /* find the first image */
00139     for(first_index = 0; first_index < 5; first_index++) {
00140         if (av_get_frame_filename(buf, sizeof(buf), path, first_index) < 0){
00141             *pfirst_index =
00142             *plast_index = 1;
00143             if (avio_check(buf, AVIO_FLAG_READ) > 0)
00144                 return 0;
00145             return -1;
00146         }
00147         if (avio_check(buf, AVIO_FLAG_READ) > 0)
00148             break;
00149     }
00150     if (first_index == 5)
00151         goto fail;
00152 
00153     /* find the last image */
00154     last_index = first_index;
00155     for(;;) {
00156         range = 0;
00157         for(;;) {
00158             if (!range)
00159                 range1 = 1;
00160             else
00161                 range1 = 2 * range;
00162             if (av_get_frame_filename(buf, sizeof(buf), path,
00163                                       last_index + range1) < 0)
00164                 goto fail;
00165             if (avio_check(buf, AVIO_FLAG_READ) <= 0)
00166                 break;
00167             range = range1;
00168             /* just in case... */
00169             if (range >= (1 << 30))
00170                 goto fail;
00171         }
00172         /* we are sure than image last_index + range exists */
00173         if (!range)
00174             break;
00175         last_index += range;
00176     }
00177     *pfirst_index = first_index;
00178     *plast_index = last_index;
00179     return 0;
00180  fail:
00181     return -1;
00182 }
00183 
00184 
00185 static int read_probe(AVProbeData *p)
00186 {
00187     if (p->filename && av_str2id(img_tags, p->filename)) {
00188         if (av_filename_number_test(p->filename))
00189             return AVPROBE_SCORE_MAX;
00190         else
00191             return AVPROBE_SCORE_MAX/2;
00192     }
00193     return 0;
00194 }
00195 
00196 enum CodecID ff_guess_image2_codec(const char *filename)
00197 {
00198     return av_str2id(img_tags, filename);
00199 }
00200 
00201 #if FF_API_GUESS_IMG2_CODEC
00202 enum CodecID av_guess_image2_codec(const char *filename){
00203     return av_str2id(img_tags, filename);
00204 }
00205 #endif
00206 
00207 static int read_header(AVFormatContext *s1, AVFormatParameters *ap)
00208 {
00209     VideoData *s = s1->priv_data;
00210     int first_index, last_index, ret = 0;
00211     int width = 0, height = 0;
00212     AVStream *st;
00213     enum PixelFormat pix_fmt = PIX_FMT_NONE;
00214     AVRational framerate;
00215 
00216     s1->ctx_flags |= AVFMTCTX_NOHEADER;
00217 
00218     st = avformat_new_stream(s1, NULL);
00219     if (!st) {
00220         return AVERROR(ENOMEM);
00221     }
00222 
00223     if (s->pixel_format && (pix_fmt = av_get_pix_fmt(s->pixel_format)) == PIX_FMT_NONE) {
00224         av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n", s->pixel_format);
00225         return AVERROR(EINVAL);
00226     }
00227     if (s->video_size && (ret = av_parse_video_size(&width, &height, s->video_size)) < 0) {
00228         av_log(s, AV_LOG_ERROR, "Could not parse video size: %s.\n", s->video_size);
00229         return ret;
00230     }
00231     if ((ret = av_parse_video_rate(&framerate, s->framerate)) < 0) {
00232         av_log(s, AV_LOG_ERROR, "Could not parse framerate: %s.\n", s->framerate);
00233         return ret;
00234     }
00235 
00236 #if FF_API_LOOP_INPUT
00237     if (s1->loop_input)
00238         s->loop = s1->loop_input;
00239 #endif
00240 
00241     av_strlcpy(s->path, s1->filename, sizeof(s->path));
00242     s->img_number = 0;
00243     s->img_count = 0;
00244 
00245     /* find format */
00246     if (s1->iformat->flags & AVFMT_NOFILE)
00247         s->is_pipe = 0;
00248     else{
00249         s->is_pipe = 1;
00250         st->need_parsing = AVSTREAM_PARSE_FULL;
00251     }
00252 
00253     avpriv_set_pts_info(st, 60, framerate.den, framerate.num);
00254 
00255     if (width && height) {
00256         st->codec->width  = width;
00257         st->codec->height = height;
00258     }
00259 
00260     if (!s->is_pipe) {
00261         if (find_image_range(&first_index, &last_index, s->path) < 0)
00262             return AVERROR(ENOENT);
00263         s->img_first = first_index;
00264         s->img_last = last_index;
00265         s->img_number = first_index;
00266         /* compute duration */
00267         st->start_time = 0;
00268         st->duration = last_index - first_index + 1;
00269     }
00270 
00271     if(s1->video_codec_id){
00272         st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00273         st->codec->codec_id = s1->video_codec_id;
00274     }else if(s1->audio_codec_id){
00275         st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00276         st->codec->codec_id = s1->audio_codec_id;
00277     }else{
00278         st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00279         st->codec->codec_id = av_str2id(img_tags, s->path);
00280     }
00281     if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO && pix_fmt != PIX_FMT_NONE)
00282         st->codec->pix_fmt = pix_fmt;
00283 
00284     return 0;
00285 }
00286 
00287 static int read_packet(AVFormatContext *s1, AVPacket *pkt)
00288 {
00289     VideoData *s = s1->priv_data;
00290     char filename[1024];
00291     int i;
00292     int size[3]={0}, ret[3]={0};
00293     AVIOContext *f[3];
00294     AVCodecContext *codec= s1->streams[0]->codec;
00295 
00296     if (!s->is_pipe) {
00297         /* loop over input */
00298         if (s->loop && s->img_number > s->img_last) {
00299             s->img_number = s->img_first;
00300         }
00301         if (s->img_number > s->img_last)
00302             return AVERROR_EOF;
00303         if (av_get_frame_filename(filename, sizeof(filename),
00304                                   s->path, s->img_number)<0 && s->img_number > 1)
00305             return AVERROR(EIO);
00306         for(i=0; i<3; i++){
00307             if (avio_open2(&f[i], filename, AVIO_FLAG_READ,
00308                            &s1->interrupt_callback, NULL) < 0) {
00309                 if(i==1)
00310                     break;
00311                 av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n",filename);
00312                 return AVERROR(EIO);
00313             }
00314             size[i]= avio_size(f[i]);
00315 
00316             if(codec->codec_id != CODEC_ID_RAWVIDEO)
00317                 break;
00318             filename[ strlen(filename) - 1 ]= 'U' + i;
00319         }
00320 
00321         if(codec->codec_id == CODEC_ID_RAWVIDEO && !codec->width)
00322             infer_size(&codec->width, &codec->height, size[0]);
00323     } else {
00324         f[0] = s1->pb;
00325         if (f[0]->eof_reached)
00326             return AVERROR(EIO);
00327         size[0]= 4096;
00328     }
00329 
00330     av_new_packet(pkt, size[0] + size[1] + size[2]);
00331     pkt->stream_index = 0;
00332     pkt->flags |= AV_PKT_FLAG_KEY;
00333 
00334     pkt->size= 0;
00335     for(i=0; i<3; i++){
00336         if(size[i]){
00337             ret[i]= avio_read(f[i], pkt->data + pkt->size, size[i]);
00338             if (!s->is_pipe)
00339                 avio_close(f[i]);
00340             if(ret[i]>0)
00341                 pkt->size += ret[i];
00342         }
00343     }
00344 
00345     if (ret[0] <= 0 || ret[1]<0 || ret[2]<0) {
00346         av_free_packet(pkt);
00347         return AVERROR(EIO); /* signal EOF */
00348     } else {
00349         s->img_count++;
00350         s->img_number++;
00351         return 0;
00352     }
00353 }
00354 
00355 #if CONFIG_IMAGE2_MUXER || CONFIG_IMAGE2PIPE_MUXER
00356 /******************************************************/
00357 /* image output */
00358 
00359 static int write_header(AVFormatContext *s)
00360 {
00361     VideoData *img = s->priv_data;
00362 
00363     img->img_number = 1;
00364     av_strlcpy(img->path, s->filename, sizeof(img->path));
00365 
00366     /* find format */
00367     if (s->oformat->flags & AVFMT_NOFILE)
00368         img->is_pipe = 0;
00369     else
00370         img->is_pipe = 1;
00371 
00372     return 0;
00373 }
00374 
00375 static int write_packet(AVFormatContext *s, AVPacket *pkt)
00376 {
00377     VideoData *img = s->priv_data;
00378     AVIOContext *pb[3];
00379     char filename[1024];
00380     AVCodecContext *codec= s->streams[ pkt->stream_index ]->codec;
00381     int i;
00382 
00383     if (!img->is_pipe) {
00384         if (av_get_frame_filename(filename, sizeof(filename),
00385                                   img->path, img->img_number) < 0 && img->img_number>1) {
00386             av_log(s, AV_LOG_ERROR,
00387                    "Could not get frame filename number %d from pattern '%s'\n",
00388                    img->img_number, img->path);
00389             return AVERROR(EIO);
00390         }
00391         for(i=0; i<3; i++){
00392             if (avio_open2(&pb[i], filename, AVIO_FLAG_WRITE,
00393                            &s->interrupt_callback, NULL) < 0) {
00394                 av_log(s, AV_LOG_ERROR, "Could not open file : %s\n",filename);
00395                 return AVERROR(EIO);
00396             }
00397 
00398             if(codec->codec_id != CODEC_ID_RAWVIDEO)
00399                 break;
00400             filename[ strlen(filename) - 1 ]= 'U' + i;
00401         }
00402     } else {
00403         pb[0] = s->pb;
00404     }
00405 
00406     if(codec->codec_id == CODEC_ID_RAWVIDEO){
00407         int ysize = codec->width * codec->height;
00408         avio_write(pb[0], pkt->data        , ysize);
00409         avio_write(pb[1], pkt->data + ysize, (pkt->size - ysize)/2);
00410         avio_write(pb[2], pkt->data + ysize +(pkt->size - ysize)/2, (pkt->size - ysize)/2);
00411         avio_flush(pb[1]);
00412         avio_flush(pb[2]);
00413         avio_close(pb[1]);
00414         avio_close(pb[2]);
00415     }else{
00416         if(av_str2id(img_tags, s->filename) == CODEC_ID_JPEG2000){
00417             AVStream *st = s->streams[0];
00418             if(st->codec->extradata_size > 8 &&
00419                AV_RL32(st->codec->extradata+4) == MKTAG('j','p','2','h')){
00420                 if(pkt->size < 8 || AV_RL32(pkt->data+4) != MKTAG('j','p','2','c'))
00421                     goto error;
00422                 avio_wb32(pb[0], 12);
00423                 ffio_wfourcc(pb[0], "jP  ");
00424                 avio_wb32(pb[0], 0x0D0A870A); // signature
00425                 avio_wb32(pb[0], 20);
00426                 ffio_wfourcc(pb[0], "ftyp");
00427                 ffio_wfourcc(pb[0], "jp2 ");
00428                 avio_wb32(pb[0], 0);
00429                 ffio_wfourcc(pb[0], "jp2 ");
00430                 avio_write(pb[0], st->codec->extradata, st->codec->extradata_size);
00431             }else if(pkt->size < 8 ||
00432                      (!st->codec->extradata_size &&
00433                       AV_RL32(pkt->data+4) != MKTAG('j','P',' ',' '))){ // signature
00434             error:
00435                 av_log(s, AV_LOG_ERROR, "malformed JPEG 2000 codestream\n");
00436                 return -1;
00437             }
00438         }
00439         avio_write(pb[0], pkt->data, pkt->size);
00440     }
00441     avio_flush(pb[0]);
00442     if (!img->is_pipe) {
00443         avio_close(pb[0]);
00444     }
00445 
00446     img->img_number++;
00447     return 0;
00448 }
00449 
00450 #endif /* CONFIG_IMAGE2_MUXER || CONFIG_IMAGE2PIPE_MUXER */
00451 
00452 #define OFFSET(x) offsetof(VideoData, x)
00453 #define DEC AV_OPT_FLAG_DECODING_PARAM
00454 static const AVOption options[] = {
00455     { "pixel_format", "", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
00456     { "video_size",   "", OFFSET(video_size),   AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
00457     { "framerate",    "", OFFSET(framerate),    AV_OPT_TYPE_STRING, {.str = "25"}, 0, 0, DEC },
00458     { "loop",         "", OFFSET(loop),         AV_OPT_TYPE_INT,    {.dbl = 0},    0, 1, DEC },
00459     { NULL },
00460 };
00461 
00462 /* input */
00463 #if CONFIG_IMAGE2_DEMUXER
00464 static const AVClass img2_class = {
00465     .class_name = "image2 demuxer",
00466     .item_name  = av_default_item_name,
00467     .option     = options,
00468     .version    = LIBAVUTIL_VERSION_INT,
00469 };
00470 AVInputFormat ff_image2_demuxer = {
00471     .name           = "image2",
00472     .long_name      = NULL_IF_CONFIG_SMALL("image2 sequence"),
00473     .priv_data_size = sizeof(VideoData),
00474     .read_probe     = read_probe,
00475     .read_header    = read_header,
00476     .read_packet    = read_packet,
00477     .flags          = AVFMT_NOFILE,
00478     .priv_class     = &img2_class,
00479 };
00480 #endif
00481 #if CONFIG_IMAGE2PIPE_DEMUXER
00482 static const AVClass img2pipe_class = {
00483     .class_name = "image2pipe demuxer",
00484     .item_name  = av_default_item_name,
00485     .option     = options,
00486     .version    = LIBAVUTIL_VERSION_INT,
00487 };
00488 AVInputFormat ff_image2pipe_demuxer = {
00489     .name           = "image2pipe",
00490     .long_name      = NULL_IF_CONFIG_SMALL("piped image2 sequence"),
00491     .priv_data_size = sizeof(VideoData),
00492     .read_header    = read_header,
00493     .read_packet    = read_packet,
00494     .priv_class     = &img2pipe_class,
00495 };
00496 #endif
00497 
00498 /* output */
00499 #if CONFIG_IMAGE2_MUXER
00500 AVOutputFormat ff_image2_muxer = {
00501     .name           = "image2",
00502     .long_name      = NULL_IF_CONFIG_SMALL("image2 sequence"),
00503     .extensions     = "bmp,dpx,jpeg,jpg,ljpg,pam,pbm,pcx,pgm,pgmyuv,png,"
00504                       "ppm,sgi,tga,tif,tiff,jp2",
00505     .priv_data_size = sizeof(VideoData),
00506     .video_codec    = CODEC_ID_MJPEG,
00507     .write_header   = write_header,
00508     .write_packet   = write_packet,
00509     .flags          = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS | AVFMT_NOFILE
00510 };
00511 #endif
00512 #if CONFIG_IMAGE2PIPE_MUXER
00513 AVOutputFormat ff_image2pipe_muxer = {
00514     .name           = "image2pipe",
00515     .long_name      = NULL_IF_CONFIG_SMALL("piped image2 sequence"),
00516     .priv_data_size = sizeof(VideoData),
00517     .video_codec    = CODEC_ID_MJPEG,
00518     .write_header   = write_header,
00519     .write_packet   = write_packet,
00520     .flags          = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS
00521 };
00522 #endif