Libav 0.7.1
|
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 #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 char path[1024]; 00042 char *pixel_format; 00043 char *video_size; 00044 char *framerate; 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 (!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 = av_new_stream(s1, 0); 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 #if FF_API_FORMAT_PARAMETERS 00236 if (ap->pix_fmt != PIX_FMT_NONE) 00237 pix_fmt = ap->pix_fmt; 00238 if (ap->width > 0) 00239 width = ap->width; 00240 if (ap->height > 0) 00241 height = ap->height; 00242 if (ap->time_base.num) 00243 framerate = (AVRational){ap->time_base.den, ap->time_base.num}; 00244 #endif 00245 00246 av_strlcpy(s->path, s1->filename, sizeof(s->path)); 00247 s->img_number = 0; 00248 s->img_count = 0; 00249 00250 /* find format */ 00251 if (s1->iformat->flags & AVFMT_NOFILE) 00252 s->is_pipe = 0; 00253 else{ 00254 s->is_pipe = 1; 00255 st->need_parsing = AVSTREAM_PARSE_FULL; 00256 } 00257 00258 av_set_pts_info(st, 60, framerate.den, framerate.num); 00259 00260 if (width && height) { 00261 st->codec->width = width; 00262 st->codec->height = height; 00263 } 00264 00265 if (!s->is_pipe) { 00266 if (find_image_range(&first_index, &last_index, s->path) < 0) 00267 return AVERROR(ENOENT); 00268 s->img_first = first_index; 00269 s->img_last = last_index; 00270 s->img_number = first_index; 00271 /* compute duration */ 00272 st->start_time = 0; 00273 st->duration = last_index - first_index + 1; 00274 } 00275 00276 if(s1->video_codec_id){ 00277 st->codec->codec_type = AVMEDIA_TYPE_VIDEO; 00278 st->codec->codec_id = s1->video_codec_id; 00279 }else if(s1->audio_codec_id){ 00280 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; 00281 st->codec->codec_id = s1->audio_codec_id; 00282 }else{ 00283 st->codec->codec_type = AVMEDIA_TYPE_VIDEO; 00284 st->codec->codec_id = av_str2id(img_tags, s->path); 00285 } 00286 if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO && pix_fmt != PIX_FMT_NONE) 00287 st->codec->pix_fmt = pix_fmt; 00288 00289 return 0; 00290 } 00291 00292 static int read_packet(AVFormatContext *s1, AVPacket *pkt) 00293 { 00294 VideoData *s = s1->priv_data; 00295 char filename[1024]; 00296 int i; 00297 int size[3]={0}, ret[3]={0}; 00298 AVIOContext *f[3]; 00299 AVCodecContext *codec= s1->streams[0]->codec; 00300 00301 if (!s->is_pipe) { 00302 /* loop over input */ 00303 if (s1->loop_input && s->img_number > s->img_last) { 00304 s->img_number = s->img_first; 00305 } 00306 if (s->img_number > s->img_last) 00307 return AVERROR_EOF; 00308 if (av_get_frame_filename(filename, sizeof(filename), 00309 s->path, s->img_number)<0 && s->img_number > 1) 00310 return AVERROR(EIO); 00311 for(i=0; i<3; i++){ 00312 if (avio_open(&f[i], filename, AVIO_FLAG_READ) < 0) { 00313 if(i==1) 00314 break; 00315 av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n",filename); 00316 return AVERROR(EIO); 00317 } 00318 size[i]= avio_size(f[i]); 00319 00320 if(codec->codec_id != CODEC_ID_RAWVIDEO) 00321 break; 00322 filename[ strlen(filename) - 1 ]= 'U' + i; 00323 } 00324 00325 if(codec->codec_id == CODEC_ID_RAWVIDEO && !codec->width) 00326 infer_size(&codec->width, &codec->height, size[0]); 00327 } else { 00328 f[0] = s1->pb; 00329 if (f[0]->eof_reached) 00330 return AVERROR(EIO); 00331 size[0]= 4096; 00332 } 00333 00334 av_new_packet(pkt, size[0] + size[1] + size[2]); 00335 pkt->stream_index = 0; 00336 pkt->flags |= AV_PKT_FLAG_KEY; 00337 00338 pkt->size= 0; 00339 for(i=0; i<3; i++){ 00340 if(size[i]){ 00341 ret[i]= avio_read(f[i], pkt->data + pkt->size, size[i]); 00342 if (!s->is_pipe) 00343 avio_close(f[i]); 00344 if(ret[i]>0) 00345 pkt->size += ret[i]; 00346 } 00347 } 00348 00349 if (ret[0] <= 0 || ret[1]<0 || ret[2]<0) { 00350 av_free_packet(pkt); 00351 return AVERROR(EIO); /* signal EOF */ 00352 } else { 00353 s->img_count++; 00354 s->img_number++; 00355 return 0; 00356 } 00357 } 00358 00359 #if CONFIG_IMAGE2_MUXER || CONFIG_IMAGE2PIPE_MUXER 00360 /******************************************************/ 00361 /* image output */ 00362 00363 static int write_header(AVFormatContext *s) 00364 { 00365 VideoData *img = s->priv_data; 00366 00367 img->img_number = 1; 00368 av_strlcpy(img->path, s->filename, sizeof(img->path)); 00369 00370 /* find format */ 00371 if (s->oformat->flags & AVFMT_NOFILE) 00372 img->is_pipe = 0; 00373 else 00374 img->is_pipe = 1; 00375 00376 return 0; 00377 } 00378 00379 static int write_packet(AVFormatContext *s, AVPacket *pkt) 00380 { 00381 VideoData *img = s->priv_data; 00382 AVIOContext *pb[3]; 00383 char filename[1024]; 00384 AVCodecContext *codec= s->streams[ pkt->stream_index ]->codec; 00385 int i; 00386 00387 if (!img->is_pipe) { 00388 if (av_get_frame_filename(filename, sizeof(filename), 00389 img->path, img->img_number) < 0 && img->img_number>1) { 00390 av_log(s, AV_LOG_ERROR, 00391 "Could not get frame filename number %d from pattern '%s'\n", 00392 img->img_number, img->path); 00393 return AVERROR(EIO); 00394 } 00395 for(i=0; i<3; i++){ 00396 if (avio_open(&pb[i], filename, AVIO_FLAG_WRITE) < 0) { 00397 av_log(s, AV_LOG_ERROR, "Could not open file : %s\n",filename); 00398 return AVERROR(EIO); 00399 } 00400 00401 if(codec->codec_id != CODEC_ID_RAWVIDEO) 00402 break; 00403 filename[ strlen(filename) - 1 ]= 'U' + i; 00404 } 00405 } else { 00406 pb[0] = s->pb; 00407 } 00408 00409 if(codec->codec_id == CODEC_ID_RAWVIDEO){ 00410 int ysize = codec->width * codec->height; 00411 avio_write(pb[0], pkt->data , ysize); 00412 avio_write(pb[1], pkt->data + ysize, (pkt->size - ysize)/2); 00413 avio_write(pb[2], pkt->data + ysize +(pkt->size - ysize)/2, (pkt->size - ysize)/2); 00414 avio_flush(pb[1]); 00415 avio_flush(pb[2]); 00416 avio_close(pb[1]); 00417 avio_close(pb[2]); 00418 }else{ 00419 if(av_str2id(img_tags, s->filename) == CODEC_ID_JPEG2000){ 00420 AVStream *st = s->streams[0]; 00421 if(st->codec->extradata_size > 8 && 00422 AV_RL32(st->codec->extradata+4) == MKTAG('j','p','2','h')){ 00423 if(pkt->size < 8 || AV_RL32(pkt->data+4) != MKTAG('j','p','2','c')) 00424 goto error; 00425 avio_wb32(pb[0], 12); 00426 ffio_wfourcc(pb[0], "jP "); 00427 avio_wb32(pb[0], 0x0D0A870A); // signature 00428 avio_wb32(pb[0], 20); 00429 ffio_wfourcc(pb[0], "ftyp"); 00430 ffio_wfourcc(pb[0], "jp2 "); 00431 avio_wb32(pb[0], 0); 00432 ffio_wfourcc(pb[0], "jp2 "); 00433 avio_write(pb[0], st->codec->extradata, st->codec->extradata_size); 00434 }else if(pkt->size < 8 || 00435 (!st->codec->extradata_size && 00436 AV_RL32(pkt->data+4) != MKTAG('j','P',' ',' '))){ // signature 00437 error: 00438 av_log(s, AV_LOG_ERROR, "malformated jpeg2000 codestream\n"); 00439 return -1; 00440 } 00441 } 00442 avio_write(pb[0], pkt->data, pkt->size); 00443 } 00444 avio_flush(pb[0]); 00445 if (!img->is_pipe) { 00446 avio_close(pb[0]); 00447 } 00448 00449 img->img_number++; 00450 return 0; 00451 } 00452 00453 #endif /* CONFIG_IMAGE2_MUXER || CONFIG_IMAGE2PIPE_MUXER */ 00454 00455 #define OFFSET(x) offsetof(VideoData, x) 00456 #define DEC AV_OPT_FLAG_DECODING_PARAM 00457 static const AVOption options[] = { 00458 { "pixel_format", "", OFFSET(pixel_format), FF_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, 00459 { "video_size", "", OFFSET(video_size), FF_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, 00460 { "framerate", "", OFFSET(framerate), FF_OPT_TYPE_STRING, {.str = "25"}, 0, 0, DEC }, 00461 { NULL }, 00462 }; 00463 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 00471 /* input */ 00472 #if CONFIG_IMAGE2_DEMUXER 00473 AVInputFormat ff_image2_demuxer = { 00474 .name = "image2", 00475 .long_name = NULL_IF_CONFIG_SMALL("image2 sequence"), 00476 .priv_data_size = sizeof(VideoData), 00477 .read_probe = read_probe, 00478 .read_header = read_header, 00479 .read_packet = read_packet, 00480 .flags = AVFMT_NOFILE, 00481 .priv_class = &img2_class, 00482 }; 00483 #endif 00484 #if CONFIG_IMAGE2PIPE_DEMUXER 00485 AVInputFormat ff_image2pipe_demuxer = { 00486 .name = "image2pipe", 00487 .long_name = NULL_IF_CONFIG_SMALL("piped image2 sequence"), 00488 .priv_data_size = sizeof(VideoData), 00489 .read_header = read_header, 00490 .read_packet = read_packet, 00491 .priv_class = &img2_class, 00492 }; 00493 #endif 00494 00495 /* output */ 00496 #if CONFIG_IMAGE2_MUXER 00497 AVOutputFormat ff_image2_muxer = { 00498 .name = "image2", 00499 .long_name = NULL_IF_CONFIG_SMALL("image2 sequence"), 00500 .extensions = "bmp,dpx,jpeg,jpg,ljpg,pam,pbm,pcx,pgm,pgmyuv,png," 00501 "ppm,sgi,tga,tif,tiff,jp2", 00502 .priv_data_size = sizeof(VideoData), 00503 .video_codec = CODEC_ID_MJPEG, 00504 .write_header = write_header, 00505 .write_packet = write_packet, 00506 .flags = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS | AVFMT_NOFILE 00507 }; 00508 #endif 00509 #if CONFIG_IMAGE2PIPE_MUXER 00510 AVOutputFormat ff_image2pipe_muxer = { 00511 .name = "image2pipe", 00512 .long_name = NULL_IF_CONFIG_SMALL("piped image2 sequence"), 00513 .priv_data_size = sizeof(VideoData), 00514 .video_codec = CODEC_ID_MJPEG, 00515 .write_header = write_header, 00516 .write_packet = write_packet, 00517 .flags = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS 00518 }; 00519 #endif