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/avstring.h"
00024 #include "libavutil/log.h"
00025 #include "libavutil/opt.h"
00026 #include "libavutil/pixdesc.h"
00027 #include "libavutil/parseutils.h"
00028 #include "avformat.h"
00029 #include "internal.h"
00030 #if HAVE_GLOB
00031 #include <glob.h>
00032
00033
00034
00035 #ifndef GLOB_NOMAGIC
00036 #define GLOB_NOMAGIC 0
00037 #endif
00038 #ifndef GLOB_BRACE
00039 #define GLOB_BRACE 0
00040 #endif
00041
00042 #endif
00043
00044 typedef struct {
00045 const AVClass *class;
00046 int img_first;
00047 int img_last;
00048 int img_number;
00049 int img_count;
00050 int is_pipe;
00051 int split_planes;
00052 char path[1024];
00053 char *pixel_format;
00054 char *video_size;
00055 char *framerate;
00056 int loop;
00057 int use_glob;
00058 #if HAVE_GLOB
00059 glob_t globstate;
00060 #endif
00061 } VideoDemuxData;
00062
00063 static const int sizes[][2] = {
00064 { 640, 480 },
00065 { 720, 480 },
00066 { 720, 576 },
00067 { 352, 288 },
00068 { 352, 240 },
00069 { 160, 128 },
00070 { 512, 384 },
00071 { 640, 352 },
00072 { 640, 240 },
00073 };
00074
00075 static int infer_size(int *width_ptr, int *height_ptr, int size)
00076 {
00077 int i;
00078
00079 for(i=0;i<FF_ARRAY_ELEMS(sizes);i++) {
00080 if ((sizes[i][0] * sizes[i][1]) == size) {
00081 *width_ptr = sizes[i][0];
00082 *height_ptr = sizes[i][1];
00083 return 0;
00084 }
00085 }
00086 return -1;
00087 }
00088
00089 static int is_glob(const char *path)
00090 {
00091 #if HAVE_GLOB
00092 size_t span = 0;
00093 const char *p = path;
00094
00095 while (p = strchr(p, '%')) {
00096 if (*(++p) == '%') {
00097 ++p;
00098 continue;
00099 }
00100 if (span = strspn(p, "*?[]{}"))
00101 break;
00102 }
00103
00104 return span != 0;
00105 #else
00106 return 0;
00107 #endif
00108 }
00109
00110
00111 static int find_image_range(int *pfirst_index, int *plast_index,
00112 const char *path)
00113 {
00114 char buf[1024];
00115 int range, last_index, range1, first_index;
00116
00117
00118 for(first_index = 0; first_index < 5; first_index++) {
00119 if (av_get_frame_filename(buf, sizeof(buf), path, first_index) < 0){
00120 *pfirst_index =
00121 *plast_index = 1;
00122 if (avio_check(buf, AVIO_FLAG_READ) > 0)
00123 return 0;
00124 return -1;
00125 }
00126 if (avio_check(buf, AVIO_FLAG_READ) > 0)
00127 break;
00128 }
00129 if (first_index == 5)
00130 goto fail;
00131
00132
00133 last_index = first_index;
00134 for(;;) {
00135 range = 0;
00136 for(;;) {
00137 if (!range)
00138 range1 = 1;
00139 else
00140 range1 = 2 * range;
00141 if (av_get_frame_filename(buf, sizeof(buf), path,
00142 last_index + range1) < 0)
00143 goto fail;
00144 if (avio_check(buf, AVIO_FLAG_READ) <= 0)
00145 break;
00146 range = range1;
00147
00148 if (range >= (1 << 30))
00149 goto fail;
00150 }
00151
00152 if (!range)
00153 break;
00154 last_index += range;
00155 }
00156 *pfirst_index = first_index;
00157 *plast_index = last_index;
00158 return 0;
00159 fail:
00160 return -1;
00161 }
00162
00163
00164 static int read_probe(AVProbeData *p)
00165 {
00166 if (p->filename && ff_guess_image2_codec(p->filename)) {
00167 if (av_filename_number_test(p->filename))
00168 return AVPROBE_SCORE_MAX;
00169 else if (is_glob(p->filename))
00170 return AVPROBE_SCORE_MAX;
00171 else
00172 return AVPROBE_SCORE_MAX/2;
00173 }
00174 return 0;
00175 }
00176
00177 static int read_header(AVFormatContext *s1)
00178 {
00179 VideoDemuxData *s = s1->priv_data;
00180 int first_index, last_index, ret = 0;
00181 int width = 0, height = 0;
00182 AVStream *st;
00183 enum PixelFormat pix_fmt = PIX_FMT_NONE;
00184 AVRational framerate;
00185
00186 s1->ctx_flags |= AVFMTCTX_NOHEADER;
00187
00188 st = avformat_new_stream(s1, NULL);
00189 if (!st) {
00190 return AVERROR(ENOMEM);
00191 }
00192
00193 if (s->pixel_format && (pix_fmt = av_get_pix_fmt(s->pixel_format)) == PIX_FMT_NONE) {
00194 av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n", s->pixel_format);
00195 return AVERROR(EINVAL);
00196 }
00197 if (s->video_size && (ret = av_parse_video_size(&width, &height, s->video_size)) < 0) {
00198 av_log(s, AV_LOG_ERROR, "Could not parse video size: %s.\n", s->video_size);
00199 return ret;
00200 }
00201 if ((ret = av_parse_video_rate(&framerate, s->framerate)) < 0) {
00202 av_log(s, AV_LOG_ERROR, "Could not parse framerate: %s.\n", s->framerate);
00203 return ret;
00204 }
00205
00206 av_strlcpy(s->path, s1->filename, sizeof(s->path));
00207 s->img_number = 0;
00208 s->img_count = 0;
00209
00210
00211 if (s1->iformat->flags & AVFMT_NOFILE)
00212 s->is_pipe = 0;
00213 else{
00214 s->is_pipe = 1;
00215 st->need_parsing = AVSTREAM_PARSE_FULL;
00216 }
00217
00218 avpriv_set_pts_info(st, 60, framerate.den, framerate.num);
00219
00220 if (width && height) {
00221 st->codec->width = width;
00222 st->codec->height = height;
00223 }
00224
00225 if (!s->is_pipe) {
00226 s->use_glob = is_glob(s->path);
00227 if (s->use_glob) {
00228 #if HAVE_GLOB
00229 char *p = s->path, *q, *dup;
00230 int gerr;
00231
00232 dup = q = av_strdup(p);
00233 while (*q) {
00234
00235 if ((p - s->path) >= (sizeof(s->path) - 2))
00236 break;
00237 if (*q == '%' && strspn(q + 1, "%*?[]{}"))
00238 ++q;
00239 else if (strspn(q, "\\*?[]{}"))
00240 *p++ = '\\';
00241 *p++ = *q++;
00242 }
00243 *p = 0;
00244 av_free(dup);
00245
00246 gerr = glob(s->path, GLOB_NOCHECK|GLOB_BRACE|GLOB_NOMAGIC, NULL, &s->globstate);
00247 if (gerr != 0) {
00248 return AVERROR(ENOENT);
00249 }
00250 first_index = 0;
00251 last_index = s->globstate.gl_pathc - 1;
00252 #endif
00253 } else {
00254 if (find_image_range(&first_index, &last_index, s->path) < 0)
00255 return AVERROR(ENOENT);
00256 }
00257 s->img_first = first_index;
00258 s->img_last = last_index;
00259 s->img_number = first_index;
00260
00261 st->start_time = 0;
00262 st->duration = last_index - first_index + 1;
00263 }
00264
00265 if(s1->video_codec_id){
00266 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00267 st->codec->codec_id = s1->video_codec_id;
00268 }else if(s1->audio_codec_id){
00269 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00270 st->codec->codec_id = s1->audio_codec_id;
00271 }else{
00272 const char *str= strrchr(s->path, '.');
00273 s->split_planes = str && !av_strcasecmp(str + 1, "y");
00274 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00275 st->codec->codec_id = ff_guess_image2_codec(s->path);
00276 if (st->codec->codec_id == CODEC_ID_LJPEG)
00277 st->codec->codec_id = CODEC_ID_MJPEG;
00278 }
00279 if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO && pix_fmt != PIX_FMT_NONE)
00280 st->codec->pix_fmt = pix_fmt;
00281
00282 return 0;
00283 }
00284
00285 static int read_packet(AVFormatContext *s1, AVPacket *pkt)
00286 {
00287 VideoDemuxData *s = s1->priv_data;
00288 char filename_bytes[1024];
00289 char *filename = filename_bytes;
00290 int i;
00291 int size[3]={0}, ret[3]={0};
00292 AVIOContext *f[3];
00293 AVCodecContext *codec= s1->streams[0]->codec;
00294
00295 if (!s->is_pipe) {
00296
00297 if (s->loop && s->img_number > s->img_last) {
00298 s->img_number = s->img_first;
00299 }
00300 if (s->img_number > s->img_last)
00301 return AVERROR_EOF;
00302 if (s->use_glob) {
00303 #if HAVE_GLOB
00304 filename = s->globstate.gl_pathv[s->img_number];
00305 #endif
00306 } else {
00307 if (av_get_frame_filename(filename_bytes, sizeof(filename_bytes),
00308 s->path, s->img_number)<0 && s->img_number > 1)
00309 return AVERROR(EIO);
00310 }
00311 for(i=0; i<3; i++){
00312 if (avio_open2(&f[i], filename, AVIO_FLAG_READ,
00313 &s1->interrupt_callback, NULL) < 0) {
00314 if(i==1)
00315 break;
00316 av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n",filename);
00317 return AVERROR(EIO);
00318 }
00319 size[i]= avio_size(f[i]);
00320
00321 if(!s->split_planes)
00322 break;
00323 filename[ strlen(filename) - 1 ]= 'U' + i;
00324 }
00325
00326 if(codec->codec_id == CODEC_ID_RAWVIDEO && !codec->width)
00327 infer_size(&codec->width, &codec->height, size[0]);
00328 } else {
00329 f[0] = s1->pb;
00330 if (url_feof(f[0]))
00331 return AVERROR(EIO);
00332 size[0]= 4096;
00333 }
00334
00335 av_new_packet(pkt, size[0] + size[1] + size[2]);
00336 pkt->stream_index = 0;
00337 pkt->flags |= AV_PKT_FLAG_KEY;
00338
00339 pkt->size= 0;
00340 for(i=0; i<3; i++){
00341 if(size[i]){
00342 ret[i]= avio_read(f[i], pkt->data + pkt->size, size[i]);
00343 if (!s->is_pipe)
00344 avio_close(f[i]);
00345 if(ret[i]>0)
00346 pkt->size += ret[i];
00347 }
00348 }
00349
00350 if (ret[0] <= 0 || ret[1]<0 || ret[2]<0) {
00351 av_free_packet(pkt);
00352 return AVERROR(EIO);
00353 } else {
00354 s->img_count++;
00355 s->img_number++;
00356 return 0;
00357 }
00358 }
00359
00360 static int read_close(struct AVFormatContext* s1)
00361 {
00362 VideoDemuxData *s = s1->priv_data;
00363 #if HAVE_GLOB
00364 if (s->use_glob) {
00365 globfree(&s->globstate);
00366 }
00367 #endif
00368 return 0;
00369 }
00370
00371 #define OFFSET(x) offsetof(VideoDemuxData, x)
00372 #define DEC AV_OPT_FLAG_DECODING_PARAM
00373 static const AVOption options[] = {
00374 { "pixel_format", "", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
00375 { "video_size", "", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
00376 { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = "25"}, 0, 0, DEC },
00377 { "loop", "", OFFSET(loop), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 1, DEC },
00378 { NULL },
00379 };
00380
00381 #if CONFIG_IMAGE2_DEMUXER
00382 static const AVClass img2_class = {
00383 .class_name = "image2 demuxer",
00384 .item_name = av_default_item_name,
00385 .option = options,
00386 .version = LIBAVUTIL_VERSION_INT,
00387 };
00388 AVInputFormat ff_image2_demuxer = {
00389 .name = "image2",
00390 .long_name = NULL_IF_CONFIG_SMALL("image2 sequence"),
00391 .priv_data_size = sizeof(VideoDemuxData),
00392 .read_probe = read_probe,
00393 .read_header = read_header,
00394 .read_packet = read_packet,
00395 .read_close = read_close,
00396 .flags = AVFMT_NOFILE,
00397 .priv_class = &img2_class,
00398 };
00399 #endif
00400 #if CONFIG_IMAGE2PIPE_DEMUXER
00401 static const AVClass img2pipe_class = {
00402 .class_name = "image2pipe demuxer",
00403 .item_name = av_default_item_name,
00404 .option = options,
00405 .version = LIBAVUTIL_VERSION_INT,
00406 };
00407 AVInputFormat ff_image2pipe_demuxer = {
00408 .name = "image2pipe",
00409 .long_name = NULL_IF_CONFIG_SMALL("piped image2 sequence"),
00410 .priv_data_size = sizeof(VideoDemuxData),
00411 .read_header = read_header,
00412 .read_packet = read_packet,
00413 .priv_class = &img2pipe_class,
00414 };
00415 #endif