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