[FFmpeg-devel] [share a stupid and fun patch] avformat: add a fileptr protocol
"zhilizhao(赵志立)"
quinkblack at foxmail.com
Thu Oct 14 14:06:48 EEST 2021
Just share a patch, not meant for merge.
Basically, the patch adds a new protocol which looks like fd:// or pipe:,
but deals with FILE *.
You may ask why? It’s useless if the FILE *ptr is a regular one, unless
combined with
FILE *
open_memstream(char **bufp, size_t *sizep);
FILE *
fmemopen(void *restrict *buf, size_t size, const char * restrict mode);
Then you can read or write to memory directly. For example:
diff --git a/fftools/ffplay.c b/fftools/ffplay.c
index ccea0e4578..e59d524602 100644
--- a/fftools/ffplay.c
+++ b/fftools/ffplay.c
@@ -3554,7 +3554,16 @@ static void opt_input_file(void *optctx, const char *filename)
}
if (!strcmp(filename, "-"))
filename = "pipe:";
- input_filename = filename;
+
+ // This part is stupid
+ FILE *file = fopen(filename, "rb");
+ uint8_t *buf = malloc(128 << 20);
+ size_t size = fread(buf, 1, 128 << 20, file);
+ fclose(file);
+
+ // This part is interesting
+ file = fmemopen(buf, size, "rb");
+ asprintf(&input_filename, "fileptr:%p", file);
}
static int opt_codec(void *optctx, const char *opt, const char *arg)
For writing to memory, we have avio_open_dyn_buf(). For reading from meory, we have
data_uri. avio callback can handle all kinds of cases. Still, I think the
polymorphism of FILE * is interesting.
—
libavformat/Makefile | 1 +
libavformat/file.c | 84 +++++++++++++++++++++++++++++++++++++++++
libavformat/protocols.c | 1 +
3 files changed, 86 insertions(+)
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 8a1b40aafe..047ad55462 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -637,6 +637,7 @@ OBJS-$(CONFIG_MD5_PROTOCOL) += md5proto.o
OBJS-$(CONFIG_MMSH_PROTOCOL) += mmsh.o mms.o asf.o
OBJS-$(CONFIG_MMST_PROTOCOL) += mmst.o mms.o asf.o
OBJS-$(CONFIG_PIPE_PROTOCOL) += file.o
+OBJS-$(CONFIG_FILEPTR_PROTOCOL) += file.o
OBJS-$(CONFIG_PROMPEG_PROTOCOL) += prompeg.o
OBJS-$(CONFIG_RTMP_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o
OBJS-$(CONFIG_RTMPE_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o
diff --git a/libavformat/file.c b/libavformat/file.c
index 9c23f680cd..bdf56a8473 100644
--- a/libavformat/file.c
+++ b/libavformat/file.c
@@ -412,3 +412,87 @@ const URLProtocol ff_pipe_protocol = {
};
#endif /* CONFIG_PIPE_PROTOCOL */
+
+#if CONFIG_FILEPTR_PROTOCOL
+
+typedef struct FilePtrContext {
+ const AVClass *class;
+ FILE *file;
+} FilePtrContext;
+
+static int fileptr_open(URLContext *h, const char *filename, int flags)
+{
+ FilePtrContext *c = h->priv_data;
+ FILE *file;
+ av_strstart(filename, "fileptr:", &filename);
+
+ file = (FILE *)strtoll(filename, NULL, 0);
+ if(!file) {
+ av_log(h, AV_LOG_INFO, "no FILE *, open stdin/stdout instead\n");
+ if (flags & AVIO_FLAG_WRITE) {
+ file = stdout;
+ } else {
+ file = stdin;
+ }
+ }
+
+ c->file = file;
+ return 0;
+}
+
+static int fileptr_read(URLContext *h, unsigned char *buf, int size)
+{
+ FilePtrContext *c = h->priv_data;
+ int ret;
+
+ ret = fread(buf, 1, size, c->file);
+ if (!ret) {
+ if (feof(c->file))
+ return AVERROR_EOF;
+ else
+ return AVERROR(EIO);
+ }
+
+ return ret;
+}
+
+static int fileptr_write(URLContext *h, const unsigned char *buf, int size)
+{
+ FilePtrContext *c = h->priv_data;
+ int ret;
+
+ ret = fwrite(buf, 1, size, c->file);
+ if (ret != size)
+ return AVERROR(EIO);
+
+ return ret;
+}
+
+static int64_t fileptr_seek(URLContext *h, int64_t pos, int whence)
+{
+ FilePtrContext *c = h->priv_data;
+ int ret;
+ ret = fseeko(c->file, pos, whence);
+ if (ret == -1) {
+ return AVERROR(errno);
+ }
+ return ftello(c->file);
+}
+
+static const AVClass fileptr_class = {
+ .class_name = "fileptr",
+ .item_name = av_default_item_name,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+const URLProtocol ff_fileptr_protocol = {
+ .name = "fileptr",
+ .url_open = fileptr_open,
+ .url_read = fileptr_read,
+ .url_write = fileptr_write,
+ .url_seek = fileptr_seek,
+ .priv_data_size = sizeof(FilePtrContext),
+ .priv_data_class = &fileptr_class,
+};
+
+#endif
\ No newline at end of file
diff --git a/libavformat/protocols.c b/libavformat/protocols.c
index b108aa6c7e..26c065e665 100644
--- a/libavformat/protocols.c
+++ b/libavformat/protocols.c
@@ -73,6 +73,7 @@ extern const URLProtocol ff_libsrt_protocol;
extern const URLProtocol ff_libssh_protocol;
extern const URLProtocol ff_libsmbclient_protocol;
extern const URLProtocol ff_libzmq_protocol;
+extern const URLProtocol ff_fileptr_protocol;
#include "libavformat/protocol_list.c"
--
2.31.1
More information about the ffmpeg-devel
mailing list