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

Generated on Wed Apr 11 2012 07:31:36 for FFmpeg by  doxygen 1.7.1