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