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