[FFmpeg-devel] [PATCH 9/9] lavf: add attachment pseudo-demuxer.
Nicolas George
george at nsup.org
Thu Apr 17 10:17:47 CEST 2014
TODO changelog version bump
Signed-off-by: Nicolas George <george at nsup.org>
---
doc/demuxers.texi | 35 ++++++++++++
libavformat/Makefile | 1 +
libavformat/allformats.c | 1 +
libavformat/attachmentdec.c | 133 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 170 insertions(+)
create mode 100644 libavformat/attachmentdec.c
diff --git a/doc/demuxers.texi b/doc/demuxers.texi
index f0a14e0..a246bf8 100644
--- a/doc/demuxers.texi
+++ b/doc/demuxers.texi
@@ -40,6 +40,41 @@ This demuxer is used to demux ASF files and MMS network streams.
Do not try to resynchronize by looking for a certain optional start code.
@end table
+ at section attachment
+
+Attachment pseudo demuxer: this demuxer can read any file as a single
+attachment.
+
+This demuxer accepts the following option:
+
+ at table @option
+
+ at item filename
+The declared file name of the attachment (@code{filename} metadata entry).
+If not set, the base name of the actual input file name is used.
+
+ at item mime_type
+ at item mimetype
+The declared MIME type of the attachment (@code{mimetype} metadata entry).
+If not set, defaults to the MIME type associated to the codec, or
+ at code{application/octet-stream}.
+
+ at item codec
+ at item file_codec
+The detected codec of the attachment.
+If not set, defaults to the codec associated to the MIME type, or binary
+data.
+
+ at end table
+
+Example: attach a font file to a Matroska file:
+ at example
+ffmpeg -i input_raw.ts -i subtitles.ass \
+ -f attachment -file_codec ttf -i /path/to/DejaVuSans.ttf \
+ -map 0:0 -c:v ... -map 0:1 -c:a ... -map 1 -c:s copy -map 2 \
+ output.mkv
+ at end example
+
@anchor{concat}
@section concat
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 3df5c88..3c69219 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -81,6 +81,7 @@ OBJS-$(CONFIG_ASS_DEMUXER) += assdec.o subtitles.o
OBJS-$(CONFIG_ASS_MUXER) += assenc.o
OBJS-$(CONFIG_AST_DEMUXER) += ast.o astdec.o
OBJS-$(CONFIG_AST_MUXER) += ast.o astenc.o
+OBJS-$(CONFIG_ATTACHMENT_DEMUXER) += attachmentdec.o
OBJS-$(CONFIG_AU_DEMUXER) += au.o pcm.o
OBJS-$(CONFIG_AU_MUXER) += au.o rawenc.o
OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index b5cbbef..72f2ef2 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -79,6 +79,7 @@ void av_register_all(void)
REGISTER_MUXDEMUX(ASS, ass);
REGISTER_MUXDEMUX(AST, ast);
REGISTER_MUXER (ASF_STREAM, asf_stream);
+ REGISTER_DEMUXER (ATTACHMENT, attachment);
REGISTER_MUXDEMUX(AU, au);
REGISTER_MUXDEMUX(AVI, avi);
REGISTER_DEMUXER (AVISYNTH, avisynth);
diff --git a/libavformat/attachmentdec.c b/libavformat/attachmentdec.c
new file mode 100644
index 0000000..fab4634
--- /dev/null
+++ b/libavformat/attachmentdec.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2014 Nicolas George
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/avstring.h"
+#include "libavutil/dict.h"
+#include "libavutil/opt.h"
+#include "avformat.h"
+#include "internal.h"
+
+typedef struct AttachmentContext {
+ const AVClass *class;
+ char *filename;
+ char *mime_type;
+ char *codec_name;
+} AttachmentContext;
+
+static const AVCodecDescriptor *find_codec_by_mime_type(const char *t)
+{
+ const AVCodecDescriptor *cd = NULL;
+ int i;
+
+ while ((cd = avcodec_descriptor_next(cd))) {
+ if (!cd->mime_types)
+ continue;
+ for (i = 0; cd->mime_types[i]; i++)
+ if (!strcmp(cd->mime_types[i], t))
+ return cd;
+ }
+ return NULL;
+}
+
+static int attachment_read_header(AVFormatContext *s)
+{
+ AttachmentContext *att = s->priv_data;
+ AVStream *st;
+ int64_t size;
+ const AVCodecDescriptor *cd = NULL;
+ const char *filename = att->filename, *mime_type = att->mime_type;
+ int ret;
+
+ size = avio_size(s->pb);
+ if (size <= 0) {
+ av_log(s, AV_LOG_ERROR, "Unknown file size\n");
+ return size < 0 ? size : AVERROR_PATCHWELCOME;
+ }
+ if (size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) {
+ av_log(s, AV_LOG_ERROR, "File is too big (max size %d)\n",
+ INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE);
+ return AVERROR_INVALIDDATA;
+ }
+ if (!(st = avformat_new_stream(s, NULL)))
+ return AVERROR(ENOMEM);
+ if ((ret = ff_get_extradata(st->codec, s->pb, size)) < 0)
+ return ret;
+
+ if (!filename && *s->filename)
+ filename = av_basename(s->filename);
+ if (att->codec_name) {
+ if (!(cd = avcodec_descriptor_get_by_name(att->codec_name))) {
+ av_log(s, AV_LOG_ERROR, "Unknown codec: %s\n", att->codec_name);
+ return AVERROR(EINVAL);
+ }
+ }
+ if (mime_type && !cd)
+ cd = find_codec_by_mime_type(att->mime_type);
+ if (cd && !mime_type && cd->mime_types)
+ mime_type = cd->mime_types[0];
+ if (!mime_type)
+ mime_type = "application/octet-stream";
+
+ st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT;
+ st->codec->codec_id = cd ? cd->id : AV_CODEC_ID_BIN_DATA;
+ if (filename && *filename)
+ if ((ret = av_dict_set(&st->metadata, "filename", filename, 0)) < 0)
+ return AVERROR(ENOMEM);
+ if (*mime_type)
+ if ((ret = av_dict_set(&st->metadata, "mimetype", mime_type, 0)) < 0)
+ return AVERROR(ENOMEM);
+ return 0;
+}
+
+static int attachment_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ return AVERROR_EOF;
+}
+
+#define OFFSET(field) offsetof(AttachmentContext, field)
+#define D AV_OPT_FLAG_DECODING_PARAM
+
+static const AVOption attachment_options[] = {
+ { "filename", "filename", OFFSET(filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, D },
+ { "mime_type", "MIME type", OFFSET(mime_type), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, D },
+ { "mimetype", "MIME type", OFFSET(mime_type), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, D },
+ { "codec", "codec name", OFFSET(codec_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, D },
+ { "file_codec", "codec name", OFFSET(codec_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, D },
+ { NULL }
+};
+
+#undef OFFSET
+#undef D
+
+static const AVClass attachment_class = {
+ .class_name = "attachment",
+ .item_name = av_default_item_name,
+ .option = attachment_options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+AVInputFormat ff_attachment_demuxer = {
+ .name = "attachment",
+ .long_name = NULL_IF_CONFIG_SMALL("single attached file"),
+ .priv_class = &attachment_class,
+ .priv_data_size = sizeof(AttachmentContext),
+ .read_header = attachment_read_header,
+ .read_packet = attachment_read_packet,
+};
--
1.7.10.4
More information about the ffmpeg-devel
mailing list