#include "libavutil/pixdesc.h"
#include "libavutil/parseutils.h"
#include "libavutil/intreadwrite.h"
+#include "libavcodec/gif.h"
#include "avformat.h"
#include "avio_internal.h"
#include "internal.h"
return -1;
}
-static int img_read_probe(AVProbeData *p)
+static int img_read_probe(const AVProbeData *p)
{
if (p->filename && ff_guess_image2_codec(p->filename)) {
if (av_filename_number_test(p->filename))
avpriv_set_pts_info(st, 64, 1, 1000000000);
} else if (s->ts_from_file)
avpriv_set_pts_info(st, 64, 1, 1);
- else
+ else {
avpriv_set_pts_info(st, 64, s->framerate.den, s->framerate.num);
+ st->avg_frame_rate = st->r_frame_rate = s->framerate;
+ }
if (s->width && s->height) {
st->codecpar->width = s->width;
}
if (s1->flags & AVFMT_FLAG_CUSTOM_IO) {
avio_seek(s1->pb, 0, SEEK_SET);
+ av_freep(&probe_buffer);
} else
ffio_rewind_with_probe_data(s1->pb, &probe_buffer, probe_buffer_size);
}
return 0;
}
+/**
+ * Add this frame's source path and basename to packet's sidedata
+ * as a dictionary, so it can be used by filters like 'drawtext'.
+ */
+static int add_filename_as_pkt_side_data(char *filename, AVPacket *pkt) {
+ AVDictionary *d = NULL;
+ char *packed_metadata = NULL;
+ size_t metadata_len;
+ int ret;
+
+ av_dict_set(&d, "lavf.image2dec.source_path", filename, 0);
+ av_dict_set(&d, "lavf.image2dec.source_basename", av_basename(filename), 0);
+
+ packed_metadata = av_packet_pack_dictionary(d, &metadata_len);
+ av_dict_free(&d);
+ if (!packed_metadata)
+ return AVERROR(ENOMEM);
+ ret = av_packet_add_side_data(pkt, AV_PKT_DATA_STRINGS_METADATA,
+ packed_metadata, metadata_len);
+ if (ret < 0) {
+ av_freep(&packed_metadata);
+ return ret;
+ }
+ return 0;
+}
+
int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt)
{
VideoDemuxData *s = s1->priv_data;
if (par->codec_id == AV_CODEC_ID_NONE) {
AVProbeData pd = { 0 };
- AVInputFormat *ifmt;
+ const AVInputFormat *ifmt;
uint8_t header[PROBE_BUF_MIN + AVPROBE_PADDING_SIZE];
int ret;
int score = 0;
if (s->is_pipe)
pkt->pos = avio_tell(f[0]);
+ /*
+ * export_path_metadata must be explicitly enabled via
+ * command line options for path metadata to be exported
+ * as packet side_data.
+ */
+ if (!s->is_pipe && s->export_path_metadata == 1) {
+ res = add_filename_as_pkt_side_data(filename, pkt);
+ if (res < 0)
+ goto fail;
+ }
+
pkt->size = 0;
for (i = 0; i < 3; i++) {
if (f[i]) {
}
if (ret[0] <= 0 || ret[1] < 0 || ret[2] < 0) {
- av_packet_unref(pkt);
if (ret[0] < 0) {
res = ret[0];
} else if (ret[1] < 0) {
int index = av_index_search_timestamp(st, timestamp, flags);
if(index < 0)
return -1;
- s1->img_number = st->index_entries[index].pos;
+ s1->img_number = st->internal->index_entries[index].pos;
return 0;
}
#define OFFSET(x) offsetof(VideoDemuxData, x)
#define DEC AV_OPT_FLAG_DECODING_PARAM
-const AVOption ff_img_options[] = {
- { "framerate", "set the video framerate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC },
- { "loop", "force loop over input file sequence", OFFSET(loop), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, DEC },
+#define COMMON_OPTIONS \
+ { "framerate", "set the video framerate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC }, \
+ { "pixel_format", "set video pixel format", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, \
+ { "video_size", "set video size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC }, \
+ { "loop", "force loop over input file sequence", OFFSET(loop), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, DEC }, \
+ { NULL },
+#if CONFIG_IMAGE2_DEMUXER
+const AVOption ff_img_options[] = {
{ "pattern_type", "set pattern type", OFFSET(pattern_type), AV_OPT_TYPE_INT, {.i64=PT_DEFAULT}, 0, INT_MAX, DEC, "pattern_type"},
{ "glob_sequence","select glob/sequence pattern type", 0, AV_OPT_TYPE_CONST, {.i64=PT_GLOB_SEQUENCE}, INT_MIN, INT_MAX, DEC, "pattern_type" },
{ "glob", "select glob pattern type", 0, AV_OPT_TYPE_CONST, {.i64=PT_GLOB }, INT_MIN, INT_MAX, DEC, "pattern_type" },
{ "sequence", "select sequence pattern type", 0, AV_OPT_TYPE_CONST, {.i64=PT_SEQUENCE }, INT_MIN, INT_MAX, DEC, "pattern_type" },
{ "none", "disable pattern matching", 0, AV_OPT_TYPE_CONST, {.i64=PT_NONE }, INT_MIN, INT_MAX, DEC, "pattern_type" },
-
- { "pixel_format", "set video pixel format", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
{ "start_number", "set first number in the sequence", OFFSET(start_number), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, DEC },
{ "start_number_range", "set range for looking at the first sequence number", OFFSET(start_number_range), AV_OPT_TYPE_INT, {.i64 = 5}, 1, INT_MAX, DEC },
- { "video_size", "set video size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC },
- { "frame_size", "force frame size in bytes", OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, DEC },
{ "ts_from_file", "set frame timestamp from file's one", OFFSET(ts_from_file), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 2, DEC, "ts_type" },
{ "none", "none", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 2, DEC, "ts_type" },
{ "sec", "second precision", 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 2, DEC, "ts_type" },
{ "ns", "nano second precision", 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 2, DEC, "ts_type" },
- { NULL },
+ { "export_path_metadata", "enable metadata containing input path information", OFFSET(export_path_metadata), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, DEC }, \
+ COMMON_OPTIONS
};
-#if CONFIG_IMAGE2_DEMUXER
static const AVClass img2_class = {
.class_name = "image2 demuxer",
.item_name = av_default_item_name,
.priv_class = &img2_class,
};
#endif
+
+const AVOption ff_img2pipe_options[] = {
+ { "frame_size", "force frame size in bytes", OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, DEC },
+ COMMON_OPTIONS
+};
+
#if CONFIG_IMAGE2PIPE_DEMUXER
static const AVClass img2pipe_class = {
.class_name = "image2pipe demuxer",
.item_name = av_default_item_name,
- .option = ff_img_options,
+ .option = ff_img2pipe_options,
.version = LIBAVUTIL_VERSION_INT,
};
AVInputFormat ff_image2pipe_demuxer = {
};
#endif
-static int bmp_probe(AVProbeData *p)
+static int bmp_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
int ihsize;
return AVPROBE_SCORE_EXTENSION / 4;
}
-static int dds_probe(AVProbeData *p)
+static int cri_probe(const AVProbeData *p)
+{
+ const uint8_t *b = p->buf;
+
+ if ( AV_RL32(b) == 1
+ && AV_RL32(b + 4) == 4
+ && AV_RN32(b + 8) == AV_RN32("DVCC"))
+ return AVPROBE_SCORE_MAX - 1;
+ return 0;
+}
+
+static int dds_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
return 0;
}
-static int dpx_probe(AVProbeData *p)
+static int dpx_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
int w, h;
return 0;
}
-static int exr_probe(AVProbeData *p)
+static int exr_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
return 0;
}
-static int j2k_probe(AVProbeData *p)
+static int j2k_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
return 0;
}
-static int jpeg_probe(AVProbeData *p)
+static int jpeg_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
int i, state = SOI;
return AVPROBE_SCORE_EXTENSION + 1;
if (state == SOS)
return AVPROBE_SCORE_EXTENSION / 2;
- return AVPROBE_SCORE_EXTENSION / 8;
+ return AVPROBE_SCORE_EXTENSION / 8 + 1;
}
-static int jpegls_probe(AVProbeData *p)
+static int jpegls_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
return 0;
}
-static int pcx_probe(AVProbeData *p)
+static int pcx_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
return AVPROBE_SCORE_EXTENSION + 1;
}
-static int qdraw_probe(AVProbeData *p)
+static int qdraw_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
return 0;
}
-static int pictor_probe(AVProbeData *p)
+static int pictor_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
return 0;
}
-static int png_probe(AVProbeData *p)
+static int png_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
return 0;
}
-static int psd_probe(AVProbeData *p)
+static int psd_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
int ret = 0;
return AVPROBE_SCORE_EXTENSION + ret;
}
-static int sgi_probe(AVProbeData *p)
+static int sgi_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
return 0;
}
-static int sunrast_probe(AVProbeData *p)
+static int sunrast_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
return 0;
}
-static int svg_probe(AVProbeData *p)
+static int svg_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
const uint8_t *end = p->buf + p->buf_size;
return 0;
}
-static int tiff_probe(AVProbeData *p)
+static int tiff_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
return 0;
}
-static int webp_probe(AVProbeData *p)
+static int webp_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
return 0;
}
-static int pbm_probe(AVProbeData *p)
+static int pbm_probe(const AVProbeData *p)
{
- return pnm_magic_check(p, 1) || pnm_magic_check(p, 4) ? pnm_probe(p) : 0;
+ return pnm_magic_check(p, 1) || pnm_magic_check(p, 4) || pnm_magic_check(p, 22) || pnm_magic_check(p, 54) ? pnm_probe(p) : 0;
}
-static inline int pgmx_probe(AVProbeData *p)
+static inline int pgmx_probe(const AVProbeData *p)
{
return pnm_magic_check(p, 2) || pnm_magic_check(p, 5) ? pnm_probe(p) : 0;
}
-static int pgm_probe(AVProbeData *p)
+static int pgm_probe(const AVProbeData *p)
{
int ret = pgmx_probe(p);
return ret && !av_match_ext(p->filename, "pgmyuv") ? ret : 0;
}
-static int pgmyuv_probe(AVProbeData *p) // custom FFmpeg format recognized by file extension
+static int pgmyuv_probe(const AVProbeData *p) // custom FFmpeg format recognized by file extension
{
int ret = pgmx_probe(p);
return ret && av_match_ext(p->filename, "pgmyuv") ? ret : 0;
}
-static int ppm_probe(AVProbeData *p)
+static int pgx_probe(const AVProbeData *p)
+{
+ const uint8_t *b = p->buf;
+ if (!memcmp(b, "PG ML ", 6))
+ return AVPROBE_SCORE_EXTENSION + 1;
+ return 0;
+}
+
+static int ppm_probe(const AVProbeData *p)
{
return pnm_magic_check(p, 3) || pnm_magic_check(p, 6) ? pnm_probe(p) : 0;
}
-static int pam_probe(AVProbeData *p)
+static int pam_probe(const AVProbeData *p)
{
return pnm_magic_check(p, 7) ? pnm_probe(p) : 0;
}
-static int xpm_probe(AVProbeData *p)
+static int xbm_probe(const AVProbeData *p)
+{
+ if (!memcmp(p->buf, "/* XBM X10 format */", 20))
+ return AVPROBE_SCORE_MAX;
+
+ if (!memcmp(p->buf, "#define", 7))
+ return AVPROBE_SCORE_MAX - 1;
+ return 0;
+}
+
+static int xpm_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
return 0;
}
-static int xwd_probe(AVProbeData *p)
+static int xwd_probe(const AVProbeData *p)
{
const uint8_t *b = p->buf;
unsigned width, bpp, bpad, lsize;
return AVPROBE_SCORE_MAX / 2 + 1;
}
+static int gif_probe(const AVProbeData *p)
+{
+ /* check magick */
+ if (memcmp(p->buf, gif87a_sig, 6) && memcmp(p->buf, gif89a_sig, 6))
+ return 0;
+
+ /* width or height contains zero? */
+ if (!AV_RL16(&p->buf[6]) || !AV_RL16(&p->buf[8]))
+ return 0;
+
+ return AVPROBE_SCORE_MAX - 1;
+}
+
+static int photocd_probe(const AVProbeData *p)
+{
+ if (!memcmp(p->buf, "PCD_OPA", 7))
+ return AVPROBE_SCORE_MAX - 1;
+
+ if (p->buf_size < 0x807 || memcmp(p->buf + 0x800, "PCD_IPI", 7))
+ return 0;
+
+ return AVPROBE_SCORE_MAX - 1;
+}
+
#define IMAGEAUTO_DEMUXER(imgname, codecid)\
static const AVClass imgname ## _class = {\
.class_name = AV_STRINGIFY(imgname) " demuxer",\
.item_name = av_default_item_name,\
- .option = ff_img_options,\
+ .option = ff_img2pipe_options,\
.version = LIBAVUTIL_VERSION_INT,\
};\
AVInputFormat ff_image_ ## imgname ## _pipe_demuxer = {\
};
IMAGEAUTO_DEMUXER(bmp, AV_CODEC_ID_BMP)
+IMAGEAUTO_DEMUXER(cri, AV_CODEC_ID_CRI)
IMAGEAUTO_DEMUXER(dds, AV_CODEC_ID_DDS)
IMAGEAUTO_DEMUXER(dpx, AV_CODEC_ID_DPX)
IMAGEAUTO_DEMUXER(exr, AV_CODEC_ID_EXR)
+IMAGEAUTO_DEMUXER(gif, AV_CODEC_ID_GIF)
IMAGEAUTO_DEMUXER(j2k, AV_CODEC_ID_JPEG2000)
IMAGEAUTO_DEMUXER(jpeg, AV_CODEC_ID_MJPEG)
IMAGEAUTO_DEMUXER(jpegls, AV_CODEC_ID_JPEGLS)
IMAGEAUTO_DEMUXER(pcx, AV_CODEC_ID_PCX)
IMAGEAUTO_DEMUXER(pgm, AV_CODEC_ID_PGM)
IMAGEAUTO_DEMUXER(pgmyuv, AV_CODEC_ID_PGMYUV)
+IMAGEAUTO_DEMUXER(pgx, AV_CODEC_ID_PGX)
+IMAGEAUTO_DEMUXER(photocd, AV_CODEC_ID_PHOTOCD)
IMAGEAUTO_DEMUXER(pictor, AV_CODEC_ID_PICTOR)
IMAGEAUTO_DEMUXER(png, AV_CODEC_ID_PNG)
IMAGEAUTO_DEMUXER(ppm, AV_CODEC_ID_PPM)
IMAGEAUTO_DEMUXER(svg, AV_CODEC_ID_SVG)
IMAGEAUTO_DEMUXER(tiff, AV_CODEC_ID_TIFF)
IMAGEAUTO_DEMUXER(webp, AV_CODEC_ID_WEBP)
+IMAGEAUTO_DEMUXER(xbm, AV_CODEC_ID_XBM)
IMAGEAUTO_DEMUXER(xpm, AV_CODEC_ID_XPM)
IMAGEAUTO_DEMUXER(xwd, AV_CODEC_ID_XWD)