[FFmpeg-devel] [PATCH] libavformat/keyframes: output keyframe indexes

Jonathan Viney jonathan.viney at gmail.com
Sun May 3 16:35:45 CEST 2015


Hi,

First patch here. I wrote this format to be able to get the keyframe
indexes faster than seemed possible with ffprobe, and also to get more
familiar with ffmpeg.

ffmpeg -i input.mkv -c copy -f keyframes -keyframes_filename keyframes.txt
/dev/null

Could something like this be included in ffmpeg? Or is this already
achievable with the current code?

Cheers,
-Jonathan.


---
 libavformat/Makefile     |  1 +
 libavformat/allformats.c |  1 +
 libavformat/keyframes.c  | 96
++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 98 insertions(+)
 create mode 100644 libavformat/keyframes.c

diff --git a/libavformat/Makefile b/libavformat/Makefile
index 8d9a770..b78a753 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -221,6 +221,7 @@ OBJS-$(CONFIG_IVF_MUXER)                 += ivfenc.o
 OBJS-$(CONFIG_JACOSUB_DEMUXER)           += jacosubdec.o subtitles.o
 OBJS-$(CONFIG_JACOSUB_MUXER)             += jacosubenc.o rawenc.o
 OBJS-$(CONFIG_JV_DEMUXER)                += jvdec.o
+OBJS-$(CONFIG_KEYFRAMES_MUXER)           += keyframes.o
 OBJS-$(CONFIG_LATM_DEMUXER)              += rawdec.o
 OBJS-$(CONFIG_LATM_MUXER)                += latmenc.o rawenc.o
 OBJS-$(CONFIG_LMLM4_DEMUXER)             += lmlm4.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index e6a9d01..f1da759 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -164,6 +164,7 @@ void av_register_all(void)
     REGISTER_MUXDEMUX(IVF,              ivf);
     REGISTER_MUXDEMUX(JACOSUB,          jacosub);
     REGISTER_DEMUXER (JV,               jv);
+    REGISTER_MUXER   (KEYFRAMES,        keyframes);
     REGISTER_MUXDEMUX(LATM,             latm);
     REGISTER_DEMUXER (LMLM4,            lmlm4);
     REGISTER_DEMUXER (LOAS,             loas);
diff --git a/libavformat/keyframes.c b/libavformat/keyframes.c
new file mode 100644
index 0000000..da6e054
--- /dev/null
+++ b/libavformat/keyframes.c
@@ -0,0 +1,96 @@
+/*
+ * Output keyframe indexes.
+ *
+ * Copyright (c) 2015 Jonathan Viney
+ *
+ * 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 "avformat.h"
+#include "libavutil/opt.h"
+
+typedef struct {
+    const AVClass *class;
+    int frame_count;
+    char *filename;
+    FILE *file;
+} KeyFramesContext;
+
+av_cold static int kf_init(AVFormatContext *s)
+{
+    KeyFramesContext *kf = s->priv_data;
+
+    kf->file = fopen(kf->filename, "w");
+
+    if (kf->file) {
+        av_log(s, AV_LOG_ERROR, "failed opening key frames file: %s\n",
kf->filename);
+        return -1;
+    }
+
+    return 0;
+}
+
+static int kf_write_packet(struct AVFormatContext *s, AVPacket *pkt)
+{
+    KeyFramesContext *kf = s->priv_data;
+
+    if (pkt->flags & AV_PKT_FLAG_KEY) {
+        av_log(s, AV_LOG_DEBUG, "key frame at index %d\n",
kf->frame_count);
+
+        if (fprintf(kf->file, "%d\n", kf->frame_count) < 0) {
+            av_log(s, AV_LOG_ERROR, "failed writing to key frames file\n");
+            return -1;
+        }
+    }
+
+    kf->frame_count++;
+
+    return 0;
+}
+
+av_cold static int kf_uninit(AVFormatContext *s)
+{
+    KeyFramesContext *kf = s->priv_data;
+    fclose(kf->file);
+    kf->file = NULL;
+    return 0;
+}
+
+#define OFFSET(x) offsetof(KeyFramesContext, x)
+static const AVOption options[] = {
+    { "keyframes_filename",  "output file for key frame indexes",
OFFSET(filename), AV_OPT_TYPE_STRING, { .str = "keyframes.txt" }, CHAR_MIN,
CHAR_MAX, AV_OPT_FLAG_ENCODING_PARAM },
+    { NULL }
+};
+
+static const AVClass keyframes_class = {
+    .class_name = "keyframes",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+AVOutputFormat ff_keyframes_muxer = {
+    .name           = "keyframes",
+    .long_name      = NULL_IF_CONFIG_SMALL("Output keyframe indexes."),
+    .priv_data_size = sizeof(KeyFramesContext),
+    .flags          = AVFMT_NOFILE | AVFMT_GLOBALHEADER,
+    .video_codec    = AV_CODEC_ID_RAWVIDEO,
+    .write_header   = kf_init,
+    .write_packet   = kf_write_packet,
+    .write_trailer  = kf_uninit,
+    .priv_class     = &keyframes_class
+};
-- 
2.3.7


More information about the ffmpeg-devel mailing list