Index: cherokee/handler_streaming.c
===================================================================
--- cherokee/handler_streaming.c	(revision 2867)
+++ cherokee/handler_streaming.c	(working copy)
@@ -29,10 +29,13 @@
 #include "connection-protected.h"
 #include "avl.h"
 #include "util.h"
+#include "mp4-parser.h"
 
 #define ENTRIES    "streaming"
 #define FLV_HEADER "FLV\x1\x1\0\0\0\x9\0\0\0\x9"
 
+#define is_flv     (hdl->filetype == sft_flv)
+#define is_mp4     (hdl->filetype == sft_mp4)
 
 /* Global 'stream rate' cache
  */
@@ -156,10 +159,11 @@
 	n->avformat      = NULL;
 #endif
 	n->start         = -1;
-	n->start_flv     = false;
+	n->start_header  = false;
 	n->start_time    = -1;
 	n->auto_rate_bps = -1;
 	n->boost_until   = 0;
+	n->filetype      = sft_none;
 
 	/* Return the object
 	 */
@@ -412,14 +416,180 @@
 }
 #endif
 
+/* In this method we attempt to identify the FTYP and MOOV
+ * if we have it we prepend it to the stream we are about
+ * to send to the crowd. TODO: cache this along the file
+ *
+ * This code is based on the fantastic work of Mike Melanson
+ * and came from the FFmpeg project.
+ * We would like to thank them for their great work :-)
+ */
 
+
+static ret_t
+header_mp4 (cherokee_handler_streaming_t *hdl, cherokee_buffer_t *buffer) {
+	FILE *infile;
+	unsigned char atom_bytes[ATOM_PREAMBLE_SIZE];
+	uint32_t atom_type = 0;
+	uint64_t atom_size = 0;
+	unsigned char *moov_atom;
+	unsigned char *ftyp_atom = 0;
+	uint64_t moov_atom_size;
+	uint64_t ftyp_atom_size = 0;
+	uint64_t i, j;
+	uint32_t offset_count;
+	uint64_t current_offset;
+	cherokee_boolean_t gotmoov = false;
+	unsigned int atom_counter = 0;
+	
+	infile = fopen(hdl->local_file.buf, "rb");
+	if (!infile)
+		return ret_error;
+	
+	while (!feof(infile) && !gotmoov) {
+	        if (fread(atom_bytes, ATOM_PREAMBLE_SIZE, 1, infile) != 1) {
+	            break;
+	        }
+	        atom_size = (uint32_t)BE_32(&atom_bytes[0]);
+	        atom_type = BE_32(&atom_bytes[4]);
+
+	        if ((atom_type != FREE_ATOM) &&
+	            (atom_type != JUNK_ATOM) &&
+	            (atom_type != MDAT_ATOM) &&
+	            (atom_type != MOOV_ATOM) &&
+	            (atom_type != PNOT_ATOM) &&
+	            (atom_type != SKIP_ATOM) &&
+	            (atom_type != WIDE_ATOM) &&
+	            (atom_type != PICT_ATOM) &&
+	            (atom_type != FTYP_ATOM)) {
+		    TRACE ("mp4", "encountered non-QT top-level atom (is this a Quicktime file?)\n");
+	            break;
+	        }
+
+	        /* keep ftyp and moov atoms */
+		switch (atom_type) {
+			case FTYP_ATOM: {
+		            ftyp_atom_size = atom_size;
+		            ftyp_atom = malloc(ftyp_atom_size);
+		            if (!ftyp_atom) {
+		                TRACE ("mp4", "could not allocate 0x%llX byte for ftyp atom\n", atom_size);
+		                fclose(infile);
+	        	        return ret_error;
+		            }
+		            fseeko(infile, -ATOM_PREAMBLE_SIZE, SEEK_CUR);
+		            if (fread(ftyp_atom, atom_size, 1, infile) != 1) {
+		                free(ftyp_atom);
+	        	        fclose(infile);
+		                return ret_error;
+		            }
+
+			    cherokee_buffer_add (buffer, ftyp_atom, ftyp_atom_size);
+			    free(ftyp_atom);
+		            continue;
+		        }
+
+	        	case MOOV_ATOM: {
+		            moov_atom_size = atom_size;
+		            moov_atom = malloc(moov_atom_size);
+		            if (!moov_atom) {
+		                TRACE ("mp4", "could not allocate 0x%llX byte for ftyp atom\n", atom_size);
+		                fclose(infile);
+		                return ret_error;
+		            }
+		            fseeko(infile, -ATOM_PREAMBLE_SIZE, SEEK_CUR);
+		            if (fread(moov_atom, atom_size, 1, infile) != 1) {
+		                free(moov_atom);
+	        	        fclose(infile);
+		                return ret_error;
+		            }
+			    break;
+			}
+//			default:
+				/* do nothing */
+	        }
+
+
+	        /* 64-bit special case */
+	        if (atom_size == 1) {
+	            if (fread(atom_bytes, ATOM_PREAMBLE_SIZE, 1, infile) != 1) {
+	                break;
+	            }
+	            atom_size = BE_64(&atom_bytes[0]);
+	            fseeko(infile, atom_size - ATOM_PREAMBLE_SIZE * 2, SEEK_CUR);
+	        } else {
+	            fseeko(infile, atom_size - ATOM_PREAMBLE_SIZE, SEEK_CUR);
+	        }
+
+		atom_counter++;
+	}
+
+	fclose(infile);
+
+	if (atom_counter != 1) {
+		if (BE_32(&moov_atom[12]) == CMOV_ATOM) {
+			TRACE ("mp4", "this utility does not support compressed moov atoms yet\n");
+			free(moov_atom);
+			return ret_error;
+		}
+
+	        /* crawl through the moov chunk in search of stco or co64 atoms */
+	        for (i = 4; i < moov_atom_size - 4; i++) {
+	 	       atom_type = BE_32(&moov_atom[i]);
+		        if (atom_type == STCO_ATOM) {
+		            TRACE ("mp4", " patching stco atom...\n");
+		            atom_size = BE_32(&moov_atom[i - 4]);
+		            if (i + atom_size - 4 > moov_atom_size) {
+		                TRACE ("mp4"," bad atom size\n");
+		                free(moov_atom);
+		                return ret_error;
+		            }
+		            offset_count = BE_32(&moov_atom[i + 8]);
+		            for (j = 0; j < offset_count; j++) {
+		                current_offset = BE_32(&moov_atom[i + 12 + j * 4]);
+		                current_offset += moov_atom_size;
+		                moov_atom[i + 12 + j * 4 + 0] = (current_offset >> 24) & 0xFF;
+		                moov_atom[i + 12 + j * 4 + 1] = (current_offset >> 16) & 0xFF;
+		                moov_atom[i + 12 + j * 4 + 2] = (current_offset >>  8) & 0xFF;
+		                moov_atom[i + 12 + j * 4 + 3] = (current_offset >>  0) & 0xFF;
+		            }
+		            i += atom_size - 4;
+		        } else if (atom_type == CO64_ATOM) {
+		            TRACE ("mp4"," patching co64 atom...\n");
+		            atom_size = BE_32(&moov_atom[i - 4]);
+		            if (i + atom_size - 4 > moov_atom_size) {
+		                TRACE ("mp4"," bad atom size\n");
+		                free(moov_atom);
+		                return ret_error;
+		            }
+		            offset_count = BE_32(&moov_atom[i + 8]);
+		            for (j = 0; j < offset_count; j++) {
+		                current_offset = BE_64(&moov_atom[i + 12 + j * 8]);
+		                current_offset += moov_atom_size;
+		                moov_atom[i + 12 + j * 8 + 0] = (current_offset >> 56) & 0xFF;
+		                moov_atom[i + 12 + j * 8 + 1] = (current_offset >> 48) & 0xFF;
+		                moov_atom[i + 12 + j * 8 + 2] = (current_offset >> 40) & 0xFF;
+		                moov_atom[i + 12 + j * 8 + 3] = (current_offset >> 32) & 0xFF;
+		                moov_atom[i + 12 + j * 8 + 4] = (current_offset >> 24) & 0xFF;
+		                moov_atom[i + 12 + j * 8 + 5] = (current_offset >> 16) & 0xFF;
+		                moov_atom[i + 12 + j * 8 + 6] = (current_offset >>  8) & 0xFF;
+		                moov_atom[i + 12 + j * 8 + 7] = (current_offset >>  0) & 0xFF;
+		            }
+		            i += atom_size - 4;
+		        }
+		}
+	}
+
+	cherokee_buffer_add (buffer, moov_atom, moov_atom_size);
+	free(moov_atom);
+
+	return ret_ok;
+}
+
 ret_t
 cherokee_handler_streaming_init (cherokee_handler_streaming_t *hdl)
 {
 	ret_t                               ret;
 	void                               *value;
-	cherokee_boolean_t                  is_flv = false;
-	cherokee_boolean_t                  is_mp4 = false;
 	cherokee_buffer_t                  *mime   = NULL;
 	cherokee_connection_t              *conn   = HANDLER_CONN(hdl);
 	cherokee_handler_streaming_props_t *props  = HDL_STREAMING_PROP(hdl);
@@ -443,11 +613,12 @@
 	
 	if (mime != NULL) {
 		if (cherokee_buffer_cmp_str (mime, "video/x-flv") == 0) {
-			is_flv = true;
+			hdl->filetype = sft_flv;
 		} else if (cherokee_buffer_cmp_str (mime, "video/mp4") == 0) {
-			is_mp4 = true;
+			hdl->filetype = sft_mp4;
 		}
-	}
+	} else
+		hdl->filetype = sft_none; /* Is this required, it should be none */
 
 	/* Parse arguments
 	 */
@@ -477,7 +648,7 @@
 		if (unlikely (ret != ret_ok)) {
 			return ret_error;
 		}
-		hdl->start_flv = true;
+		hdl->start_header = true;
 
 	} else if ((is_mp4) && (hdl->start_time > 0)) {
 		ret = open_media_file (hdl);
@@ -524,11 +695,18 @@
 {
 	cherokee_connection_t *conn = HANDLER_CONN(hdl);
 
-	/* FLV's "start" parameter
+	/* Some mediaformats require a proper header.
 	 */
-	if (hdl->start_flv) {
-		cherokee_buffer_add_str (buffer, FLV_HEADER);
-		hdl->start_flv = false;
+	if (hdl->start_header) {
+		if (is_flv)
+			cherokee_buffer_add_str (buffer, FLV_HEADER);
+		else if (is_mp4) {
+			/* If this function fails no disaster happens
+			 * we stream out the file anyway just no fast start
+			 */
+			header_mp4(hdl, buffer);
+		}
+		hdl->start_header = false;
 		return ret_ok;
 	}
 
Index: cherokee/handler_streaming.h
===================================================================
--- cherokee/handler_streaming.h	(revision 2867)
+++ cherokee/handler_streaming.h	(working copy)
@@ -38,6 +38,12 @@
 
 /* Data types
  */
+typedef enum {
+	sft_none,
+	sft_flv,
+	sft_mp4
+} cherokee_streaming_filetype_t;
+
 typedef struct {
 	cherokee_module_props_t        base;
 	cherokee_boolean_t             auto_rate;
@@ -50,12 +56,13 @@
 	cherokee_handler_t             handler;
 	cherokee_handler_file_t       *handler_file;
 	cherokee_buffer_t              local_file;
+	cherokee_streaming_filetype_t  filetype;
 #ifdef USE_FFMPEG
 	AVFormatContext               *avformat;
 #endif
 	cint_t                         auto_rate_bps;
 	off_t                          start;
-	cherokee_boolean_t             start_flv;
+	cherokee_boolean_t             start_header;
 	float                          start_time;
 	off_t                          boost_until;
 } cherokee_handler_streaming_t;
Index: cherokee/mp4-parser.h
===================================================================
--- cherokee/mp4-parser.h	(revision 0)
+++ cherokee/mp4-parser.h	(revision 0)
@@ -0,0 +1,43 @@
+#ifdef __MINGW32__
+#define fseeko(x,y,z)  fseeko64(x,y,z)
+#define ftello(x)      ftello64(x)
+#endif
+
+#define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1])
+#define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \
+                  (((uint8_t*)(x))[1] << 16) | \
+                  (((uint8_t*)(x))[2] << 8) | \
+                   ((uint8_t*)(x))[3])
+#define BE_64(x) (((uint64_t)(((uint8_t*)(x))[0]) << 56) | \
+                  ((uint64_t)(((uint8_t*)(x))[1]) << 48) | \
+                  ((uint64_t)(((uint8_t*)(x))[2]) << 40) | \
+                  ((uint64_t)(((uint8_t*)(x))[3]) << 32) | \
+                  ((uint64_t)(((uint8_t*)(x))[4]) << 24) | \
+                  ((uint64_t)(((uint8_t*)(x))[5]) << 16) | \
+                  ((uint64_t)(((uint8_t*)(x))[6]) << 8) | \
+                  ((uint64_t)((uint8_t*)(x))[7]))
+
+#define BE_FOURCC( ch0, ch1, ch2, ch3 )             \
+        ( (uint32_t)(unsigned char)(ch3) |          \
+        ( (uint32_t)(unsigned char)(ch2) << 8 ) |   \
+        ( (uint32_t)(unsigned char)(ch1) << 16 ) |  \
+        ( (uint32_t)(unsigned char)(ch0) << 24 ) )
+
+#define QT_ATOM BE_FOURCC
+/* top level atoms */
+#define FREE_ATOM QT_ATOM('f', 'r', 'e', 'e')
+#define JUNK_ATOM QT_ATOM('j', 'u', 'n', 'k')
+#define MDAT_ATOM QT_ATOM('m', 'd', 'a', 't')
+#define MOOV_ATOM QT_ATOM('m', 'o', 'o', 'v')
+#define PNOT_ATOM QT_ATOM('p', 'n', 'o', 't')
+#define SKIP_ATOM QT_ATOM('s', 'k', 'i', 'p')
+#define WIDE_ATOM QT_ATOM('w', 'i', 'd', 'e')
+#define PICT_ATOM QT_ATOM('P', 'I', 'C', 'T')
+#define FTYP_ATOM QT_ATOM('f', 't', 'y', 'p')
+
+#define CMOV_ATOM QT_ATOM('c', 'm', 'o', 'v')
+#define STCO_ATOM QT_ATOM('s', 't', 'c', 'o')
+#define CO64_ATOM QT_ATOM('c', 'o', '6', '4')
+
+#define ATOM_PREAMBLE_SIZE 8
+#define COPY_BUFFER_SIZE 1024
