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 #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
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
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 (avio_check(buf, AVIO_FLAG_READ) > 0)
00147 return 0;
00148 return -1;
00149 }
00150 if (avio_check(buf, AVIO_FLAG_READ) > 0)
00151 break;
00152 }
00153 if (first_index == 5)
00154 goto fail;
00155
00156
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 (avio_check(buf, AVIO_FLAG_READ) <= 0)
00169 break;
00170 range = range1;
00171
00172 if (range >= (1 << 30))
00173 goto fail;
00174 }
00175
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
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
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
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_FLAG_READ) < 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 && !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_FLAG_WRITE) < 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);
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',' ',' '))){
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
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
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
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