• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

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 FFmpeg.
00007  *
00008  * FFmpeg 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  * FFmpeg 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 FFmpeg; 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 "avformat.h"
00026 #include <strings.h>
00027 
00028 typedef struct {
00029     int img_first;
00030     int img_last;
00031     int img_number;
00032     int img_count;
00033     int is_pipe;
00034     char path[1024];
00035 } VideoData;
00036 
00037 typedef struct {
00038     enum CodecID id;
00039     const char *str;
00040 } IdStrMap;
00041 
00042 static const IdStrMap img_tags[] = {
00043     { CODEC_ID_MJPEG     , "jpeg"},
00044     { CODEC_ID_MJPEG     , "jpg"},
00045     { CODEC_ID_LJPEG     , "ljpg"},
00046     { CODEC_ID_PNG       , "png"},
00047     { CODEC_ID_PNG       , "mng"},
00048     { CODEC_ID_PPM       , "ppm"},
00049     { CODEC_ID_PPM       , "pnm"},
00050     { CODEC_ID_PGM       , "pgm"},
00051     { CODEC_ID_PGMYUV    , "pgmyuv"},
00052     { CODEC_ID_PBM       , "pbm"},
00053     { CODEC_ID_PAM       , "pam"},
00054     { CODEC_ID_MPEG1VIDEO, "mpg1-img"},
00055     { CODEC_ID_MPEG2VIDEO, "mpg2-img"},
00056     { CODEC_ID_MPEG4     , "mpg4-img"},
00057     { CODEC_ID_FFV1      , "ffv1-img"},
00058     { CODEC_ID_RAWVIDEO  , "y"},
00059     { CODEC_ID_BMP       , "bmp"},
00060     { CODEC_ID_GIF       , "gif"},
00061     { CODEC_ID_TARGA     , "tga"},
00062     { CODEC_ID_TIFF      , "tiff"},
00063     { CODEC_ID_TIFF      , "tif"},
00064     { CODEC_ID_SGI       , "sgi"},
00065     { CODEC_ID_PTX       , "ptx"},
00066     { CODEC_ID_PCX       , "pcx"},
00067     { CODEC_ID_SUNRAST   , "sun"},
00068     { CODEC_ID_SUNRAST   , "ras"},
00069     { CODEC_ID_SUNRAST   , "rs"},
00070     { CODEC_ID_SUNRAST   , "im1"},
00071     { CODEC_ID_SUNRAST   , "im8"},
00072     { CODEC_ID_SUNRAST   , "im24"},
00073     { CODEC_ID_SUNRAST   , "sunras"},
00074     { CODEC_ID_JPEG2000  , "jp2"},
00075     { CODEC_ID_DPX       , "dpx"},
00076     { CODEC_ID_NONE      , NULL}
00077 };
00078 
00079 static const int sizes[][2] = {
00080     { 640, 480 },
00081     { 720, 480 },
00082     { 720, 576 },
00083     { 352, 288 },
00084     { 352, 240 },
00085     { 160, 128 },
00086     { 512, 384 },
00087     { 640, 352 },
00088     { 640, 240 },
00089 };
00090 
00091 static int infer_size(int *width_ptr, int *height_ptr, int size)
00092 {
00093     int i;
00094 
00095     for(i=0;i<FF_ARRAY_ELEMS(sizes);i++) {
00096         if ((sizes[i][0] * sizes[i][1]) == size) {
00097             *width_ptr = sizes[i][0];
00098             *height_ptr = sizes[i][1];
00099             return 0;
00100         }
00101     }
00102     return -1;
00103 }
00104 static enum CodecID av_str2id(const IdStrMap *tags, const char *str)
00105 {
00106     str= strrchr(str, '.');
00107     if(!str) return CODEC_ID_NONE;
00108     str++;
00109 
00110     while (tags->id) {
00111         if (!strcasecmp(str, tags->str))
00112             return tags->id;
00113 
00114         tags++;
00115     }
00116     return CODEC_ID_NONE;
00117 }
00118 
00119 /* return -1 if no image found */
00120 static int find_image_range(int *pfirst_index, int *plast_index,
00121                             const char *path)
00122 {
00123     char buf[1024];
00124     int range, last_index, range1, first_index;
00125 
00126     /* find the first image */
00127     for(first_index = 0; first_index < 5; first_index++) {
00128         if (av_get_frame_filename(buf, sizeof(buf), path, first_index) < 0){
00129             *pfirst_index =
00130             *plast_index = 1;
00131             if(url_exist(buf))
00132                 return 0;
00133             return -1;
00134         }
00135         if (url_exist(buf))
00136             break;
00137     }
00138     if (first_index == 5)
00139         goto fail;
00140 
00141     /* find the last image */
00142     last_index = first_index;
00143     for(;;) {
00144         range = 0;
00145         for(;;) {
00146             if (!range)
00147                 range1 = 1;
00148             else
00149                 range1 = 2 * range;
00150             if (av_get_frame_filename(buf, sizeof(buf), path,
00151                                       last_index + range1) < 0)
00152                 goto fail;
00153             if (!url_exist(buf))
00154                 break;
00155             range = range1;
00156             /* just in case... */
00157             if (range >= (1 << 30))
00158                 goto fail;
00159         }
00160         /* we are sure than image last_index + range exists */
00161         if (!range)
00162             break;
00163         last_index += range;
00164     }
00165     *pfirst_index = first_index;
00166     *plast_index = last_index;
00167     return 0;
00168  fail:
00169     return -1;
00170 }
00171 
00172 
00173 static int image_probe(AVProbeData *p)
00174 {
00175     if (p->filename && av_str2id(img_tags, p->filename)) {
00176         if (av_filename_number_test(p->filename))
00177             return AVPROBE_SCORE_MAX;
00178         else
00179             return AVPROBE_SCORE_MAX/2;
00180     }
00181     return 0;
00182 }
00183 
00184 enum CodecID av_guess_image2_codec(const char *filename){
00185     return av_str2id(img_tags, filename);
00186 }
00187 
00188 static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap)
00189 {
00190     VideoData *s = s1->priv_data;
00191     int first_index, last_index;
00192     AVStream *st;
00193 
00194     s1->ctx_flags |= AVFMTCTX_NOHEADER;
00195 
00196     st = av_new_stream(s1, 0);
00197     if (!st) {
00198         return AVERROR(ENOMEM);
00199     }
00200 
00201     av_strlcpy(s->path, s1->filename, sizeof(s->path));
00202     s->img_number = 0;
00203     s->img_count = 0;
00204 
00205     /* find format */
00206     if (s1->iformat->flags & AVFMT_NOFILE)
00207         s->is_pipe = 0;
00208     else{
00209         s->is_pipe = 1;
00210         st->need_parsing = AVSTREAM_PARSE_FULL;
00211     }
00212 
00213     if (!ap->time_base.num) {
00214         av_set_pts_info(st, 60, 1, 25);
00215     } else {
00216         av_set_pts_info(st, 60, ap->time_base.num, ap->time_base.den);
00217     }
00218 
00219     if(ap->width && ap->height){
00220         st->codec->width = ap->width;
00221         st->codec->height= ap->height;
00222     }
00223 
00224     if (!s->is_pipe) {
00225         if (find_image_range(&first_index, &last_index, s->path) < 0)
00226             return AVERROR(ENOENT);
00227         s->img_first = first_index;
00228         s->img_last = last_index;
00229         s->img_number = first_index;
00230         /* compute duration */
00231         st->start_time = 0;
00232         st->duration = last_index - first_index + 1;
00233     }
00234 
00235     if(s1->video_codec_id){
00236         st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00237         st->codec->codec_id = s1->video_codec_id;
00238     }else if(s1->audio_codec_id){
00239         st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00240         st->codec->codec_id = s1->audio_codec_id;
00241     }else{
00242         st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00243         st->codec->codec_id = av_str2id(img_tags, s->path);
00244     }
00245     if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ap->pix_fmt != PIX_FMT_NONE)
00246         st->codec->pix_fmt = ap->pix_fmt;
00247 
00248     return 0;
00249 }
00250 
00251 static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
00252 {
00253     VideoData *s = s1->priv_data;
00254     char filename[1024];
00255     int i;
00256     int size[3]={0}, ret[3]={0};
00257     ByteIOContext *f[3];
00258     AVCodecContext *codec= s1->streams[0]->codec;
00259 
00260     if (!s->is_pipe) {
00261         /* loop over input */
00262         if (s1->loop_input && s->img_number > s->img_last) {
00263             s->img_number = s->img_first;
00264         }
00265         if (s->img_number > s->img_last)
00266             return AVERROR_EOF;
00267         if (av_get_frame_filename(filename, sizeof(filename),
00268                                   s->path, s->img_number)<0 && s->img_number > 1)
00269             return AVERROR(EIO);
00270         for(i=0; i<3; i++){
00271             if (url_fopen(&f[i], filename, URL_RDONLY) < 0) {
00272                 if(i==1)
00273                     break;
00274                 av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n",filename);
00275                 return AVERROR(EIO);
00276             }
00277             size[i]= url_fsize(f[i]);
00278 
00279             if(codec->codec_id != CODEC_ID_RAWVIDEO)
00280                 break;
00281             filename[ strlen(filename) - 1 ]= 'U' + i;
00282         }
00283 
00284         if(codec->codec_id == CODEC_ID_RAWVIDEO && !codec->width)
00285             infer_size(&codec->width, &codec->height, size[0]);
00286     } else {
00287         f[0] = s1->pb;
00288         if (url_feof(f[0]))
00289             return AVERROR(EIO);
00290         size[0]= 4096;
00291     }
00292 
00293     av_new_packet(pkt, size[0] + size[1] + size[2]);
00294     pkt->stream_index = 0;
00295     pkt->flags |= AV_PKT_FLAG_KEY;
00296 
00297     pkt->size= 0;
00298     for(i=0; i<3; i++){
00299         if(size[i]){
00300             ret[i]= get_buffer(f[i], pkt->data + pkt->size, size[i]);
00301             if (!s->is_pipe)
00302                 url_fclose(f[i]);
00303             if(ret[i]>0)
00304                 pkt->size += ret[i];
00305         }
00306     }
00307 
00308     if (ret[0] <= 0 || ret[1]<0 || ret[2]<0) {
00309         av_free_packet(pkt);
00310         return AVERROR(EIO); /* signal EOF */
00311     } else {
00312         s->img_count++;
00313         s->img_number++;
00314         return 0;
00315     }
00316 }
00317 
00318 #if CONFIG_IMAGE2_MUXER || CONFIG_IMAGE2PIPE_MUXER
00319 /******************************************************/
00320 /* image output */
00321 
00322 static int img_write_header(AVFormatContext *s)
00323 {
00324     VideoData *img = s->priv_data;
00325 
00326     img->img_number = 1;
00327     av_strlcpy(img->path, s->filename, sizeof(img->path));
00328 
00329     /* find format */
00330     if (s->oformat->flags & AVFMT_NOFILE)
00331         img->is_pipe = 0;
00332     else
00333         img->is_pipe = 1;
00334 
00335     return 0;
00336 }
00337 
00338 static int img_write_packet(AVFormatContext *s, AVPacket *pkt)
00339 {
00340     VideoData *img = s->priv_data;
00341     ByteIOContext *pb[3];
00342     char filename[1024];
00343     AVCodecContext *codec= s->streams[ pkt->stream_index ]->codec;
00344     int i;
00345 
00346     if (!img->is_pipe) {
00347         if (av_get_frame_filename(filename, sizeof(filename),
00348                                   img->path, img->img_number) < 0 && img->img_number>1) {
00349             av_log(s, AV_LOG_ERROR, "Could not get frame filename from pattern\n");
00350             return AVERROR(EIO);
00351         }
00352         for(i=0; i<3; i++){
00353             if (url_fopen(&pb[i], filename, URL_WRONLY) < 0) {
00354                 av_log(s, AV_LOG_ERROR, "Could not open file : %s\n",filename);
00355                 return AVERROR(EIO);
00356             }
00357 
00358             if(codec->codec_id != CODEC_ID_RAWVIDEO)
00359                 break;
00360             filename[ strlen(filename) - 1 ]= 'U' + i;
00361         }
00362     } else {
00363         pb[0] = s->pb;
00364     }
00365 
00366     if(codec->codec_id == CODEC_ID_RAWVIDEO){
00367         int ysize = codec->width * codec->height;
00368         put_buffer(pb[0], pkt->data        , ysize);
00369         put_buffer(pb[1], pkt->data + ysize, (pkt->size - ysize)/2);
00370         put_buffer(pb[2], pkt->data + ysize +(pkt->size - ysize)/2, (pkt->size - ysize)/2);
00371         put_flush_packet(pb[1]);
00372         put_flush_packet(pb[2]);
00373         url_fclose(pb[1]);
00374         url_fclose(pb[2]);
00375     }else{
00376         if(av_str2id(img_tags, s->filename) == CODEC_ID_JPEG2000){
00377             AVStream *st = s->streams[0];
00378             if(st->codec->extradata_size > 8 &&
00379                AV_RL32(st->codec->extradata+4) == MKTAG('j','p','2','h')){
00380                 if(pkt->size < 8 || AV_RL32(pkt->data+4) != MKTAG('j','p','2','c'))
00381                     goto error;
00382                 put_be32(pb[0], 12);
00383                 put_tag (pb[0], "jP  ");
00384                 put_be32(pb[0], 0x0D0A870A); // signature
00385                 put_be32(pb[0], 20);
00386                 put_tag (pb[0], "ftyp");
00387                 put_tag (pb[0], "jp2 ");
00388                 put_be32(pb[0], 0);
00389                 put_tag (pb[0], "jp2 ");
00390                 put_buffer(pb[0], st->codec->extradata, st->codec->extradata_size);
00391             }else if(pkt->size < 8 ||
00392                      (!st->codec->extradata_size &&
00393                       AV_RL32(pkt->data+4) != MKTAG('j','P',' ',' '))){ // signature
00394             error:
00395                 av_log(s, AV_LOG_ERROR, "malformated jpeg2000 codestream\n");
00396                 return -1;
00397             }
00398         }
00399         put_buffer(pb[0], pkt->data, pkt->size);
00400     }
00401     put_flush_packet(pb[0]);
00402     if (!img->is_pipe) {
00403         url_fclose(pb[0]);
00404     }
00405 
00406     img->img_number++;
00407     return 0;
00408 }
00409 
00410 #endif /* CONFIG_IMAGE2_MUXER || CONFIG_IMAGE2PIPE_MUXER */
00411 
00412 /* input */
00413 #if CONFIG_IMAGE2_DEMUXER
00414 AVInputFormat image2_demuxer = {
00415     "image2",
00416     NULL_IF_CONFIG_SMALL("image2 sequence"),
00417     sizeof(VideoData),
00418     image_probe,
00419     img_read_header,
00420     img_read_packet,
00421     NULL,
00422     NULL,
00423     NULL,
00424     AVFMT_NOFILE,
00425 };
00426 #endif
00427 #if CONFIG_IMAGE2PIPE_DEMUXER
00428 AVInputFormat image2pipe_demuxer = {
00429     "image2pipe",
00430     NULL_IF_CONFIG_SMALL("piped image2 sequence"),
00431     sizeof(VideoData),
00432     NULL, /* no probe */
00433     img_read_header,
00434     img_read_packet,
00435 };
00436 #endif
00437 
00438 /* output */
00439 #if CONFIG_IMAGE2_MUXER
00440 AVOutputFormat image2_muxer = {
00441     "image2",
00442     NULL_IF_CONFIG_SMALL("image2 sequence"),
00443     "",
00444     "bmp,jpeg,jpg,ljpg,pam,pbm,pcx,pgm,pgmyuv,png,ppm,sgi,tif,tiff,jp2",
00445     sizeof(VideoData),
00446     CODEC_ID_NONE,
00447     CODEC_ID_MJPEG,
00448     img_write_header,
00449     img_write_packet,
00450     NULL,
00451     .flags= AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS | AVFMT_NOFILE
00452 };
00453 #endif
00454 #if CONFIG_IMAGE2PIPE_MUXER
00455 AVOutputFormat image2pipe_muxer = {
00456     "image2pipe",
00457     NULL_IF_CONFIG_SMALL("piped image2 sequence"),
00458     "",
00459     "",
00460     sizeof(VideoData),
00461     CODEC_ID_NONE,
00462     CODEC_ID_MJPEG,
00463     img_write_header,
00464     img_write_packet,
00465     .flags= AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS
00466 };
00467 #endif

Generated on Fri Sep 16 2011 17:17:48 for FFmpeg by  doxygen 1.7.1