diff --git a/remux.c b/remux.c
index 0c46adf5bb186a2c54ddb3946fd46f620fe83aa3..1297bfce91cfbe40553a3624330eda42db1de302 100644
--- a/remux.c
+++ b/remux.c
@@ -4,41 +4,6 @@
 #include "util.h"
 #include "config.h"
 
-#define CHAPTER_TIME_BASE (AVRational){1, 1}
-
-void parse_dict(AVDictionary **d, char *s)
-{
-	char *val;
-	for (s = jenter(s); s; s = jnext(s))
-	{
-		if (val = jstr(jvalue(s), 0))
-			av_dict_set(d, jstr(s, 0), val, 0);
-		else
-			av_dict_set_int(d, jstr(s, 0), jint(jvalue(s), 0), 0);
-	}
-}
-
-void parse_chapters(AVFormatContext *ctx, char *s, int duration)
-{
-	char *p;
-	int i;
-	for (p = jenter(s), i = 0; p; p = jnext(p), i ++);
-	ctx->chapters = malloc(sizeof(AVChapter *)*i);
-	ctx->nb_chapters = i;
-	for (p = jenter(s), i = 0; p; p = jnext(p), i ++)
-	{
-		ctx->chapters[i] = malloc(sizeof(AVChapter));
-		memset(ctx->chapters[i], 0, sizeof(AVChapter));
-		ctx->chapters[i]->id = i;
-		ctx->chapters[i]->time_base = CHAPTER_TIME_BASE;
-		ctx->chapters[i]->start = jint(jlookup(p, "time"), 0);
-		av_dict_set(&ctx->chapters[i]->metadata, "title", jstr(jlookup(p, "text"), "EMPTY"), 0);
-		if (i)
-			ctx->chapters[i-1]->end = ctx->chapters[i]->start;
-	}
-	ctx->chapters[i-1]->end = duration;
-}
-
 int main(int argc, char *argv[])
 {
 	int i, err;
@@ -67,8 +32,7 @@ int main(int argc, char *argv[])
 	avformat_alloc_output_context2(&mux, 0, jstr(jlookup(argv[4], "format"), 0), path);
 	av_dict_copy(&mux->metadata, demux->metadata, 0);
 	parse_dict(&mux->metadata, jlookup(argv[4], "metadata"));
-	parse_chapters(mux, jlookup(argv[4], "chapters"),
-			av_rescale_q(demux->duration, AV_TIME_BASE_Q, CHAPTER_TIME_BASE));
+	parse_chapters(mux, jlookup(argv[4], "chapters"), demux->duration);
 	idxmap = malloc(sizeof(int)*demux->nb_streams);
 	for (i = 0; i < demux->nb_streams; i ++)
 	{
diff --git a/util.h b/util.h
index 76870b3710e3bad7472c39fa1278bf0f9aa94f3f..dd12df7eaf94f0595b426325a84a414efd4998d7 100644
--- a/util.h
+++ b/util.h
@@ -1,5 +1,7 @@
 #include <unistd.h>
 #include <stdarg.h>
+#include <libavutil/opt.h>
+#include <libavformat/avformat.h>
 
 /* Generic */
 #define SL(s) (s), (sizeof(s)-1)
@@ -9,6 +11,12 @@ extern int jobid;
 char *vmprintf(const char *fmt, va_list ap);
 char *mprintf(const char *fmt, ...);
 
+void *xmalloc(size_t size);
+
+/* JSON av parsing */
+void parse_dict(AVDictionary **d, char *s);
+void parse_chapters(AVFormatContext *ctx, char *s, int64_t duration);
+
 /* Logging */
 void init_avlogbuf(void);
 void avlogbuf_callback(void *classp, int level, const char *fmt, va_list ap);
diff --git a/util/parse_chapters.c b/util/parse_chapters.c
new file mode 100644
index 0000000000000000000000000000000000000000..cbe570ec32c7d0dc3b689d95dbebb474677a0f39
--- /dev/null
+++ b/util/parse_chapters.c
@@ -0,0 +1,29 @@
+#include <libavformat/avformat.h>
+
+#include "../util.h"
+
+#define CHAPTER_TIME_BASE (AVRational){1, 1}
+
+void parse_chapters(AVFormatContext *ctx, char *s, int64_t duration)
+{
+	char *p;
+	int i;
+	duration = av_rescale_q(duration, AV_TIME_BASE_Q, CHAPTER_TIME_BASE);
+	for (p = jenter(s), i = 0; p; p = jnext(p), i ++);
+	ctx->chapters = xmalloc(sizeof(AVChapter *)*i);
+	ctx->nb_chapters = i;
+	for (p = jenter(s), i = 0; p; p = jnext(p), i ++)
+	{
+		ctx->chapters[i] = malloc(sizeof(AVChapter));
+		memset(ctx->chapters[i], 0, sizeof(AVChapter));
+		ctx->chapters[i]->id = i;
+		ctx->chapters[i]->time_base = CHAPTER_TIME_BASE;
+		ctx->chapters[i]->start = jint(jlookup(p, "time"), 0);
+		av_dict_set(&ctx->chapters[i]->metadata, "title", jstr(jlookup(p, "text"), "EMPTY"), 0);
+		if (i)
+			ctx->chapters[i-1]->end = ctx->chapters[i]->start;
+	}
+	if (ctx->nb_chapters)
+		ctx->chapters[i-1]->end = duration;
+}
+
diff --git a/util/parse_dict.c b/util/parse_dict.c
new file mode 100644
index 0000000000000000000000000000000000000000..d5b8be0b5e0c3d6d149e847a0881f657bea0e037
--- /dev/null
+++ b/util/parse_dict.c
@@ -0,0 +1,17 @@
+#include <libavutil/opt.h>
+#include <libavformat/avformat.h>
+
+#include "../util.h"
+
+void parse_dict(AVDictionary **d, char *s)
+{
+	char *val;
+	for (s = jenter(s); s; s = jnext(s))
+	{
+		if (val = jstr(jvalue(s), 0))
+			av_dict_set(d, jstr(s, 0), val, 0);
+		else
+			av_dict_set_int(d, jstr(s, 0), jint(jvalue(s), 0), 0);
+	}
+}
+
diff --git a/util/xmalloc.c b/util/xmalloc.c
new file mode 100644
index 0000000000000000000000000000000000000000..6f7b3742c1d1347c9fbccac0942225c3eff36667
--- /dev/null
+++ b/util/xmalloc.c
@@ -0,0 +1,14 @@
+#include <string.h>
+#include <stdlib.h>
+
+#include "../util.h"
+
+void *xmalloc(size_t size)
+{
+	void *p;
+	if (!(p = malloc(size)))
+		exit(99);
+	memset(p, 0, size);
+	return p;
+}
+