00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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 int split_planes;
00041 char path[1024];
00042 char *pixel_format;
00043 char *video_size;
00044 char *framerate;
00045 int loop;
00046 int updatefirst;
00047 } VideoData;
00048
00049 typedef struct {
00050 enum CodecID id;
00051 const char *str;
00052 } IdStrMap;
00053
00054 static const IdStrMap img_tags[] = {
00055 { CODEC_ID_MJPEG , "jpeg"},
00056 { CODEC_ID_MJPEG , "jpg"},
00057 { CODEC_ID_LJPEG , "ljpg"},
00058 { CODEC_ID_JPEGLS , "jls"},
00059 { CODEC_ID_PNG , "png"},
00060 { CODEC_ID_PNG , "mng"},
00061 { CODEC_ID_PPM , "ppm"},
00062 { CODEC_ID_PPM , "pnm"},
00063 { CODEC_ID_PGM , "pgm"},
00064 { CODEC_ID_PGMYUV , "pgmyuv"},
00065 { CODEC_ID_PBM , "pbm"},
00066 { CODEC_ID_PAM , "pam"},
00067 { CODEC_ID_MPEG1VIDEO, "mpg1-img"},
00068 { CODEC_ID_MPEG2VIDEO, "mpg2-img"},
00069 { CODEC_ID_MPEG4 , "mpg4-img"},
00070 { CODEC_ID_FFV1 , "ffv1-img"},
00071 { CODEC_ID_RAWVIDEO , "y"},
00072 { CODEC_ID_RAWVIDEO , "raw"},
00073 { CODEC_ID_BMP , "bmp"},
00074 { CODEC_ID_GIF , "gif"},
00075 { CODEC_ID_TARGA , "tga"},
00076 { CODEC_ID_TIFF , "tiff"},
00077 { CODEC_ID_TIFF , "tif"},
00078 { CODEC_ID_SGI , "sgi"},
00079 { CODEC_ID_PTX , "ptx"},
00080 { CODEC_ID_PCX , "pcx"},
00081 { CODEC_ID_SUNRAST , "sun"},
00082 { CODEC_ID_SUNRAST , "ras"},
00083 { CODEC_ID_SUNRAST , "rs"},
00084 { CODEC_ID_SUNRAST , "im1"},
00085 { CODEC_ID_SUNRAST , "im8"},
00086 { CODEC_ID_SUNRAST , "im24"},
00087 { CODEC_ID_SUNRAST , "sunras"},
00088 { CODEC_ID_JPEG2000 , "j2k"},
00089 { CODEC_ID_JPEG2000 , "jp2"},
00090 { CODEC_ID_JPEG2000 , "jpc"},
00091 { CODEC_ID_DPX , "dpx"},
00092 { CODEC_ID_PICTOR , "pic"},
00093 { CODEC_ID_NONE , NULL}
00094 };
00095
00096 static const int sizes[][2] = {
00097 { 640, 480 },
00098 { 720, 480 },
00099 { 720, 576 },
00100 { 352, 288 },
00101 { 352, 240 },
00102 { 160, 128 },
00103 { 512, 384 },
00104 { 640, 352 },
00105 { 640, 240 },
00106 };
00107
00108 static int infer_size(int *width_ptr, int *height_ptr, int size)
00109 {
00110 int i;
00111
00112 for(i=0;i<FF_ARRAY_ELEMS(sizes);i++) {
00113 if ((sizes[i][0] * sizes[i][1]) == size) {
00114 *width_ptr = sizes[i][0];
00115 *height_ptr = sizes[i][1];
00116 return 0;
00117 }
00118 }
00119 return -1;
00120 }
00121 static enum CodecID av_str2id(const IdStrMap *tags, const char *str)
00122 {
00123 str= strrchr(str, '.');
00124 if(!str) return CODEC_ID_NONE;
00125 str++;
00126
00127 while (tags->id) {
00128 if (!av_strcasecmp(str, tags->str))
00129 return tags->id;
00130
00131 tags++;
00132 }
00133 return CODEC_ID_NONE;
00134 }
00135
00136
00137 static int find_image_range(int *pfirst_index, int *plast_index,
00138 const char *path)
00139 {
00140 char buf[1024];
00141 int range, last_index, range1, first_index;
00142
00143
00144 for(first_index = 0; first_index < 5; first_index++) {
00145 if (av_get_frame_filename(buf, sizeof(buf), path, first_index) < 0){
00146 *pfirst_index =
00147 *plast_index = 1;
00148 if (avio_check(buf, AVIO_FLAG_READ) > 0)
00149 return 0;
00150 return -1;
00151 }
00152 if (avio_check(buf, AVIO_FLAG_READ) > 0)
00153 break;
00154 }
00155 if (first_index == 5)
00156 goto fail;
00157
00158
00159 last_index = first_index;
00160 for(;;) {
00161 range = 0;
00162 for(;;) {
00163 if (!range)
00164 range1 = 1;
00165 else
00166 range1 = 2 * range;
00167 if (av_get_frame_filename(buf, sizeof(buf), path,
00168 last_index + range1) < 0)
00169 goto fail;
00170 if (avio_check(buf, AVIO_FLAG_READ) <= 0)
00171 break;
00172 range = range1;
00173
00174 if (range >= (1 << 30))
00175 goto fail;
00176 }
00177
00178 if (!range)
00179 break;
00180 last_index += range;
00181 }
00182 *pfirst_index = first_index;
00183 *plast_index = last_index;
00184 return 0;
00185 fail:
00186 return -1;
00187 }
00188
00189
00190 static int read_probe(AVProbeData *p)
00191 {
00192 if (p->filename && av_str2id(img_tags, p->filename)) {
00193 if (av_filename_number_test(p->filename))
00194 return AVPROBE_SCORE_MAX;
00195 else
00196 return AVPROBE_SCORE_MAX/2;
00197 }
00198 return 0;
00199 }
00200
00201 enum CodecID ff_guess_image2_codec(const char *filename)
00202 {
00203 return av_str2id(img_tags, filename);
00204 }
00205
00206 #if FF_API_GUESS_IMG2_CODEC
00207 enum CodecID av_guess_image2_codec(const char *filename){
00208 return av_str2id(img_tags, filename);
00209 }
00210 #endif
00211
00212 static int read_header(AVFormatContext *s1, AVFormatParameters *ap)
00213 {
00214 VideoData *s = s1->priv_data;
00215 int first_index, last_index, ret = 0;
00216 int width = 0, height = 0;
00217 AVStream *st;
00218 enum PixelFormat pix_fmt = PIX_FMT_NONE;
00219 AVRational framerate;
00220
00221 s1->ctx_flags |= AVFMTCTX_NOHEADER;
00222
00223 st = avformat_new_stream(s1, NULL);
00224 if (!st) {
00225 return AVERROR(ENOMEM);
00226 }
00227
00228 if (s->pixel_format && (pix_fmt = av_get_pix_fmt(s->pixel_format)) == PIX_FMT_NONE) {
00229 av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n", s->pixel_format);
00230 return AVERROR(EINVAL);
00231 }
00232 if (s->video_size && (ret = av_parse_video_size(&width, &height, s->video_size)) < 0) {
00233 av_log(s, AV_LOG_ERROR, "Could not parse video size: %s.\n", s->video_size);
00234 return ret;
00235 }
00236 if ((ret = av_parse_video_rate(&framerate, s->framerate)) < 0) {
00237 av_log(s, AV_LOG_ERROR, "Could not parse framerate: %s.\n", s->framerate);
00238 return ret;
00239 }
00240
00241 #if FF_API_LOOP_INPUT
00242 if (s1->loop_input)
00243 s->loop = s1->loop_input;
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
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 avpriv_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
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 const char *str= strrchr(s->path, '.');
00284 s->split_planes = str && !av_strcasecmp(str + 1, "y");
00285 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00286 st->codec->codec_id = av_str2id(img_tags, s->path);
00287 if (st->codec->codec_id == CODEC_ID_LJPEG)
00288 st->codec->codec_id = CODEC_ID_MJPEG;
00289 }
00290 if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO && pix_fmt != PIX_FMT_NONE)
00291 st->codec->pix_fmt = pix_fmt;
00292
00293 return 0;
00294 }
00295
00296 static int read_packet(AVFormatContext *s1, AVPacket *pkt)
00297 {
00298 VideoData *s = s1->priv_data;
00299 char filename[1024];
00300 int i;
00301 int size[3]={0}, ret[3]={0};
00302 AVIOContext *f[3];
00303 AVCodecContext *codec= s1->streams[0]->codec;
00304
00305 if (!s->is_pipe) {
00306
00307 if (s->loop && s->img_number > s->img_last) {
00308 s->img_number = s->img_first;
00309 }
00310 if (s->img_number > s->img_last)
00311 return AVERROR_EOF;
00312 if (av_get_frame_filename(filename, sizeof(filename),
00313 s->path, s->img_number)<0 && s->img_number > 1)
00314 return AVERROR(EIO);
00315 for(i=0; i<3; i++){
00316 if (avio_open2(&f[i], filename, AVIO_FLAG_READ,
00317 &s1->interrupt_callback, NULL) < 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);
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
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
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 && !av_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 && !img->updatefirst) {
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_open2(&pb[i], filename, AVIO_FLAG_WRITE,
00405 &s->interrupt_callback, NULL) < 0) {
00406 av_log(s, AV_LOG_ERROR, "Could not open file : %s\n",filename);
00407 return AVERROR(EIO);
00408 }
00409
00410 if(!img->split_planes)
00411 break;
00412 filename[ strlen(filename) - 1 ]= 'U' + i;
00413 }
00414 } else {
00415 pb[0] = s->pb;
00416 }
00417
00418 if(img->split_planes){
00419 int ysize = codec->width * codec->height;
00420 avio_write(pb[0], pkt->data , ysize);
00421 avio_write(pb[1], pkt->data + ysize, (pkt->size - ysize)/2);
00422 avio_write(pb[2], pkt->data + ysize +(pkt->size - ysize)/2, (pkt->size - ysize)/2);
00423 avio_flush(pb[1]);
00424 avio_flush(pb[2]);
00425 avio_close(pb[1]);
00426 avio_close(pb[2]);
00427 }else{
00428 if(av_str2id(img_tags, s->filename) == CODEC_ID_JPEG2000){
00429 AVStream *st = s->streams[0];
00430 if(st->codec->extradata_size > 8 &&
00431 AV_RL32(st->codec->extradata+4) == MKTAG('j','p','2','h')){
00432 if(pkt->size < 8 || AV_RL32(pkt->data+4) != MKTAG('j','p','2','c'))
00433 goto error;
00434 avio_wb32(pb[0], 12);
00435 ffio_wfourcc(pb[0], "jP ");
00436 avio_wb32(pb[0], 0x0D0A870A);
00437 avio_wb32(pb[0], 20);
00438 ffio_wfourcc(pb[0], "ftyp");
00439 ffio_wfourcc(pb[0], "jp2 ");
00440 avio_wb32(pb[0], 0);
00441 ffio_wfourcc(pb[0], "jp2 ");
00442 avio_write(pb[0], st->codec->extradata, st->codec->extradata_size);
00443 }else if(pkt->size >= 8 && AV_RB32(pkt->data) == 0xFF4FFF51){
00444
00445 }else if(pkt->size < 8 ||
00446 (!st->codec->extradata_size &&
00447 AV_RL32(pkt->data+4) != MKTAG('j','P',' ',' '))){
00448 error:
00449 av_log(s, AV_LOG_ERROR, "malformated jpeg2000 codestream %X\n", AV_RB32(pkt->data));
00450 return -1;
00451 }
00452 }
00453 avio_write(pb[0], pkt->data, pkt->size);
00454 }
00455 avio_flush(pb[0]);
00456 if (!img->is_pipe) {
00457 avio_close(pb[0]);
00458 }
00459
00460 img->img_number++;
00461 return 0;
00462 }
00463
00464 #endif
00465
00466 #define OFFSET(x) offsetof(VideoData, x)
00467 #define DEC AV_OPT_FLAG_DECODING_PARAM
00468 #define ENC AV_OPT_FLAG_ENCODING_PARAM
00469 static const AVOption options[] = {
00470 { "pixel_format", "", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
00471 { "video_size", "", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
00472 { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = "25"}, 0, 0, DEC },
00473 { "loop", "", OFFSET(loop), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 1, DEC },
00474 { NULL },
00475 };
00476
00477 static const AVOption muxoptions[] = {
00478 { "updatefirst", "", OFFSET(updatefirst), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 1, ENC },
00479 { NULL },
00480 };
00481
00482
00483 #if CONFIG_IMAGE2_DEMUXER
00484 static const AVClass img2_class = {
00485 .class_name = "image2 demuxer",
00486 .item_name = av_default_item_name,
00487 .option = options,
00488 .version = LIBAVUTIL_VERSION_INT,
00489 };
00490 AVInputFormat ff_image2_demuxer = {
00491 .name = "image2",
00492 .long_name = NULL_IF_CONFIG_SMALL("image2 sequence"),
00493 .priv_data_size = sizeof(VideoData),
00494 .read_probe = read_probe,
00495 .read_header = read_header,
00496 .read_packet = read_packet,
00497 .flags = AVFMT_NOFILE,
00498 .priv_class = &img2_class,
00499 };
00500 #endif
00501 #if CONFIG_IMAGE2PIPE_DEMUXER
00502 static const AVClass img2pipe_class = {
00503 .class_name = "image2pipe demuxer",
00504 .item_name = av_default_item_name,
00505 .option = options,
00506 .version = LIBAVUTIL_VERSION_INT,
00507 };
00508 AVInputFormat ff_image2pipe_demuxer = {
00509 .name = "image2pipe",
00510 .long_name = NULL_IF_CONFIG_SMALL("piped image2 sequence"),
00511 .priv_data_size = sizeof(VideoData),
00512 .read_header = read_header,
00513 .read_packet = read_packet,
00514 .priv_class = &img2pipe_class,
00515 };
00516 #endif
00517
00518
00519 #if CONFIG_IMAGE2_MUXER
00520 static const AVClass img2mux_class = {
00521 .class_name = "image2 muxer",
00522 .item_name = av_default_item_name,
00523 .option = muxoptions,
00524 .version = LIBAVUTIL_VERSION_INT,
00525 };
00526 AVOutputFormat ff_image2_muxer = {
00527 .name = "image2",
00528 .long_name = NULL_IF_CONFIG_SMALL("image2 sequence"),
00529 .extensions = "bmp,dpx,jls,jpeg,jpg,ljpg,pam,pbm,pcx,pgm,pgmyuv,png,"
00530 "ppm,sgi,tga,tif,tiff,jp2",
00531 .priv_data_size = sizeof(VideoData),
00532 .video_codec = CODEC_ID_MJPEG,
00533 .write_header = write_header,
00534 .write_packet = write_packet,
00535 .flags = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS | AVFMT_NOFILE,
00536 .priv_class = &img2mux_class,
00537 };
00538 #endif
00539 #if CONFIG_IMAGE2PIPE_MUXER
00540 AVOutputFormat ff_image2pipe_muxer = {
00541 .name = "image2pipe",
00542 .long_name = NULL_IF_CONFIG_SMALL("piped image2 sequence"),
00543 .priv_data_size = sizeof(VideoData),
00544 .video_codec = CODEC_ID_MJPEG,
00545 .write_header = write_header,
00546 .write_packet = write_packet,
00547 .flags = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS
00548 };
00549 #endif