From a7888c4998d52a6c85a0c5bd80c340a1a6eee867 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@duempel.org>
Date: Tue, 21 Oct 2008 18:12:56 +0200
Subject: ffmpeg: don't pass pointer as hexadecimal string

Casting a pointer to some sort of integer and formatting it into a
string isn't valid.  A pointer derived from this hex string won't work
reliably.  Since ffmpeg doesn't provide a nice API for passing our
pointer, we have to think of a different hack: ffmpeg passes the exact
URL pointer to mpdurl_open(), and we can make this string part of a
struct.  This reduces the problem to casting the string back to the
struct.

This is still a workaround, but this is "sort of portable", unless the
ffmpeg people start messing with the URL pointer (which would be valid
according to the API definition).
---
 src/inputPlugins/ffmpeg_plugin.c | 47 +++++++++++++++++++++++-----------------
 1 file changed, 27 insertions(+), 20 deletions(-)

diff --git a/src/inputPlugins/ffmpeg_plugin.c b/src/inputPlugins/ffmpeg_plugin.c
index 95e15957c..6455cd1ce 100644
--- a/src/inputPlugins/ffmpeg_plugin.c
+++ b/src/inputPlugins/ffmpeg_plugin.c
@@ -50,26 +50,34 @@ typedef struct {
 } BasePtrs;
 
 typedef struct {
+	/** hack - see url_to_base() */
+	char url[8];
+
 	struct decoder *decoder;
 	InputStream *input;
 } FopsHelper;
 
-static int mpdurl_open(URLContext *h, const char *filename, int flags)
+/**
+ * Convert a faked mpd:// URL to a FopsHelper structure.  This is a
+ * hack because ffmpeg does not provide a nice API for passing a
+ * user-defined pointer to mpdurl_open().
+ */
+static FopsHelper *url_to_base(const char *url)
 {
-	uint32_t ptr;
-	FopsHelper *base;
-	if (strlen(filename) == (8+8)) {
-		errno = 0;
-		ptr = (uint32_t) strtoll(filename + 6, NULL, 16);
-		if (errno == 0 && ptr != 0) {
-			base = (FopsHelper *) ptr;
-			h->priv_data = base;
-			h->is_streamed = (base->input->seekable ? 0 : 1);
-			return 0;
-		}
-	}
-	FATAL("Invalid format %s:%d\n", filename, flags);
-	return -1;
+	union {
+		const char *in;
+		FopsHelper *out;
+	} u = { .in = url };
+	return u.out;
+}
+
+static int mpdurl_open(URLContext *h, const char *filename,
+		       mpd_unused int flags)
+{
+	FopsHelper *base = url_to_base(filename);
+	h->priv_data = base;
+	h->is_streamed = (base->input->seekable ? 0 : 1);
+	return 0;
 }
 
 static int mpdurl_read(URLContext *h, unsigned char *buf, int size)
@@ -137,8 +145,9 @@ static int ffmpeg_helper(InputStream *input, int (*callback)(BasePtrs *ptrs),
 	AVCodec *aCodec;
 	int ret, audioStream;
 	unsigned i;
-	FopsHelper fopshelp;
-	char url[24];
+	FopsHelper fopshelp = {
+		.url = "mpd://X", /* only the mpd:// prefix matters */
+	};
 
 	fopshelp.input = input;
 	if (ptrs && ptrs->decoder) {
@@ -148,9 +157,7 @@ static int ffmpeg_helper(InputStream *input, int (*callback)(BasePtrs *ptrs),
 	}
 
 	//ffmpeg works with ours "fileops" helper
-	sprintf(url, "mpd://0x%8x", (unsigned int) &fopshelp);
-
-	if (av_open_input_file(&pFormatCtx, url, NULL, 0, NULL)!=0) {
+	if (av_open_input_file(&pFormatCtx, fopshelp.url, NULL, 0, NULL)!=0) {
 		ERROR("Open failed!\n");
 		return -1;
 	}
-- 
cgit v1.2.3