SOURCES: lighttpd-mod_h264_streaming.patch (NEW) - patch against 1...

glen glen at pld-linux.org
Tue Oct 23 22:48:47 CEST 2007


Author: glen                         Date: Tue Oct 23 20:48:47 2007 GMT
Module: SOURCES                       Tag: HEAD
---- Log message:
- patch against 1.4.18 and http://h264.code-shop.com/svn/h264 @20

---- Files affected:
SOURCES:
   lighttpd-mod_h264_streaming.patch (NONE -> 1.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/lighttpd-mod_h264_streaming.patch
diff -u /dev/null SOURCES/lighttpd-mod_h264_streaming.patch:1.1
--- /dev/null	Tue Oct 23 22:48:47 2007
+++ SOURCES/lighttpd-mod_h264_streaming.patch	Tue Oct 23 22:48:42 2007
@@ -0,0 +1,1678 @@
+diff -ur -x '*.m4' -x ltmain.sh -x install-sh -x depcomp -x Makefile.in -x compile -x 'config.*' -x configure -x missing -x mkinstalldirs -x autom4te.cache -Nur -x .svn lighttpd-1.4.18/src/Makefile.am lighttpd-mod_h264_streaming-1.4.18/src/Makefile.am
+--- lighttpd-1.4.18/src/Makefile.am	2007-09-03 01:23:53.000000000 +0300
++++ lighttpd-mod_h264_streaming-1.4.18/src/Makefile.am	2007-10-23 23:42:37.736979478 +0300
+@@ -77,6 +77,11 @@
+ mod_flv_streaming_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
+ mod_flv_streaming_la_LIBADD = $(common_libadd)
+ 
++lib_LTLIBRARIES += mod_h264_streaming.la
++mod_h264_streaming_la_SOURCES = mod_h264_streaming.c moov.c
++mod_h264_streaming_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
++mod_h264_streaming_la_LIBADD = $(common_libadd)
++
+ lib_LTLIBRARIES += mod_evasive.la
+ mod_evasive_la_SOURCES = mod_evasive.c
+ mod_evasive_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
+diff -ur -x '*.m4' -x ltmain.sh -x install-sh -x depcomp -x Makefile.in -x compile -x 'config.*' -x configure -x missing -x mkinstalldirs -x autom4te.cache -Nur -x .svn lighttpd-1.4.18/src/mod_h264_streaming.c lighttpd-mod_h264_streaming-1.4.18/src/mod_h264_streaming.c
+--- lighttpd-1.4.18/src/mod_h264_streaming.c	1970-01-01 03:00:00.000000000 +0300
++++ lighttpd-mod_h264_streaming-1.4.18/src/mod_h264_streaming.c	2007-10-23 23:42:37.696978564 +0300
+@@ -0,0 +1,467 @@
++/*******************************************************************************
++ mod_h264_streaming.c
++
++ mod_h264_streaming - A lighttpd plugin for pseudo-streaming Quicktime/MPEG4 files.
++ http://h264.code-shop.com
++
++ Copyright (C) 2007 CodeShop B.V.
++
++ This program is free software: you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation, either version 3 of the License, or
++ (at your option) any later version.
++
++ This program 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 General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program.  If not, see <http://www.gnu.org/licenses/>.
++******************************************************************************/ 
++
++#include <ctype.h>
++#include <stdlib.h>
++#include <string.h>
++#include <stdio.h>
++
++#include "base.h"
++#include "log.h"
++#include "buffer.h"
++#include "response.h"
++#include "http_chunk.h"
++#include "stat_cache.h"
++
++#include "plugin.h"
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++/* plugin config for all request/connections */
++
++typedef struct {
++	array *extensions;
++} plugin_config;
++
++typedef struct {
++	PLUGIN_DATA;
++
++	buffer *query_str;
++	array *get_params;
++
++	plugin_config **config_storage;
++
++	plugin_config conf;
++} plugin_data;
++
++/* init the plugin data */
++INIT_FUNC(mod_h264_streaming_init) {
++	plugin_data *p;
++
++	p = calloc(1, sizeof(*p));
++
++	p->query_str = buffer_init();
++	p->get_params = array_init();
++
++	return p;
++}
++
++/* detroy the plugin data */
++FREE_FUNC(mod_h264_streaming_free) {
++	plugin_data *p = p_d;
++
++	UNUSED(srv);
++
++	if (!p) return HANDLER_GO_ON;
++
++	if (p->config_storage) {
++		size_t i;
++
++		for (i = 0; i < srv->config_context->used; i++) {
++			plugin_config *s = p->config_storage[i];
++
++			if (!s) continue;
++
++			array_free(s->extensions);
++
++			free(s);
++		}
++		free(p->config_storage);
++	}
++
++	buffer_free(p->query_str);
++	array_free(p->get_params);
++
++	free(p);
++
++	return HANDLER_GO_ON;
++}
++
++/* handle plugin config and check values */
++
++SETDEFAULTS_FUNC(mod_h264_streaming_set_defaults) {
++	plugin_data *p = p_d;
++	size_t i = 0;
++
++	config_values_t cv[] = {
++		{ "h264-streaming.extensions",   NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
++		{ NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
++	};
++
++	if (!p) return HANDLER_ERROR;
++
++	p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
++
++	for (i = 0; i < srv->config_context->used; i++) {
++		plugin_config *s;
++
++		s = calloc(1, sizeof(plugin_config));
++		s->extensions     = array_init();
++
++		cv[0].destination = s->extensions;
++
++		p->config_storage[i] = s;
++
++		if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
++			return HANDLER_ERROR;
++		}
++	}
++
++	return HANDLER_GO_ON;
++}
++
++#define PATCH(x) \
++	p->conf.x = s->x;
++static int mod_h264_streaming_patch_connection(server *srv, connection *con, plugin_data *p) {
++	size_t i, j;
++	plugin_config *s = p->config_storage[0];
++
++	PATCH(extensions);
++
++	/* skip the first, the global context */
++	for (i = 1; i < srv->config_context->used; i++) {
++		data_config *dc = (data_config *)srv->config_context->data[i];
++		s = p->config_storage[i];
++
++		/* condition didn't match */
++		if (!config_check_cond(srv, con, dc)) continue;
++
++		/* merge config */
++		for (j = 0; j < dc->value->used; j++) {
++			data_unset *du = dc->value->data[j];
++
++			if (buffer_is_equal_string(du->key, CONST_STR_LEN("h264-streaming.extensions"))) {
++				PATCH(extensions);
++			}
++		}
++	}
++
++	return 0;
++}
++#undef PATCH
++
++static int split_get_params(array *get_params, buffer *qrystr) {
++	size_t is_key = 1;
++	size_t i;
++	char *key = NULL, *val = NULL;
++
++	key = qrystr->ptr;
++
++	/* we need the \0 */
++	for (i = 0; i < qrystr->used; i++) {
++		switch(qrystr->ptr[i]) {
++		case '=':
++			if (is_key) {
++				val = qrystr->ptr + i + 1;
++
++				qrystr->ptr[i] = '\0';
++
++				is_key = 0;
++			}
++
++			break;
++		case '&':
++		case '\0': /* fin symbol */
++			if (!is_key) {
++				data_string *ds;
++				/* we need at least a = since the last & */
++
++				/* terminate the value */
++				qrystr->ptr[i] = '\0';
++
++				if (NULL == (ds = (data_string *)array_get_unused_element(get_params, TYPE_STRING))) {
++					ds = data_string_init();
++				}
++				buffer_copy_string_len(ds->key, key, strlen(key));
++				buffer_copy_string_len(ds->value, val, strlen(val));
++
++				array_insert_unique(get_params, (data_unset *)ds);
++			}
++
++			key = qrystr->ptr + i + 1;
++			val = NULL;
++			is_key = 1;
++			break;
++		}
++	}
++
++	return 0;
++}
++
++extern unsigned int moov_seek(unsigned char* moov_data, unsigned int size,
++				float start_time,
++				unsigned int* mdat_start, unsigned int* mdat_size,
++				unsigned int offset);
++
++void write_char(unsigned char* outbuffer, int value)
++{
++  outbuffer[0] = (unsigned char)(value);
++}
++
++void write_int32(unsigned char* outbuffer, long value)
++{
++  outbuffer[0] = (unsigned char)((value >> 24) & 0xff);
++  outbuffer[1] = (unsigned char)((value >> 16) & 0xff);
++  outbuffer[2] = (unsigned char)((value >> 8) & 0xff);
++  outbuffer[3] = (unsigned char)((value >> 0) & 0xff);
++}
++
++struct atom_t
++{
++  unsigned char type_[4];
++  unsigned int size_;
++  unsigned int start_;
++  unsigned int end_;
++};
++
++#define ATOM_PREAMBLE_SIZE 8
++
++unsigned int atom_header_size(unsigned char* atom_bytes)
++{
++  return (atom_bytes[0] << 24) +
++         (atom_bytes[1] << 16) +
++         (atom_bytes[2] << 8) +
++         (atom_bytes[3]);
++}
++
++int atom_read_header(FILE* infile, struct atom_t* atom)
++{
++  unsigned char atom_bytes[ATOM_PREAMBLE_SIZE];
++
++  atom->start_ = ftell(infile);
++
++  fread(atom_bytes, ATOM_PREAMBLE_SIZE, 1, infile);
++  memcpy(&atom->type_[0], &atom_bytes[4], 4);
++  atom->size_ = atom_header_size(atom_bytes);
++  atom->end_ = atom->start_ + atom->size_;
++
++  return 1;
++}
++
++void atom_write_header(unsigned char* outbuffer, struct atom_t* atom)
++{
++  int i;
++  write_int32(outbuffer, atom->size_);
++  for(i = 0; i != 4; ++i)
++    write_char(outbuffer + 4 + i, atom->type_[i]);
++}
++
++int atom_is(struct atom_t const* atom, const char* type)
++{
++  return (atom->type_[0] == type[0] &&
++          atom->type_[1] == type[1] &&
++          atom->type_[2] == type[2] &&
++          atom->type_[3] == type[3])
++         ;
++}
++
++void atom_skip(FILE* infile, struct atom_t const* atom)
++{
++  fseek(infile, atom->end_, SEEK_SET);
++}
++
++void atom_print(struct atom_t const* atom)
++{
++  printf("Atom(%c%c%c%c,%d)\n", atom->type_[0], atom->type_[1],
++          atom->type_[2], atom->type_[3], atom->size_);
++}
++
++
++URIHANDLER_FUNC(mod_h264_streaming_path_handler) {
++	plugin_data *p = p_d;
++	int s_len;
++	size_t k;
++
++	UNUSED(srv);
++
++	if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON;
++
++	mod_h264_streaming_patch_connection(srv, con, p);
++
++	s_len = con->physical.path->used - 1;
++
++	for (k = 0; k < p->conf.extensions->used; k++) {
++		data_string *ds = (data_string *)p->conf.extensions->data[k];
++		int ct_len = ds->value->used - 1;
++
++		if (ct_len > s_len) continue;
++		if (ds->value->used == 0) continue;
++
++		if (0 == strncmp(con->physical.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
++			data_string *get_param;
++			stat_cache_entry *sce = NULL;
++			buffer *b;
++			double start;
++			char *err = NULL;
++			/* if there is a start=[0-9]+ in the header use it as start,
++			 * otherwise send the full file */
++
++			array_reset(p->get_params);
++			buffer_copy_string_buffer(p->query_str, con->uri.query);
++			split_get_params(p->get_params, p->query_str);
++
++			if (NULL == (get_param = (data_string *)array_get_element(p->get_params, "start"))) {
++				return HANDLER_GO_ON;
++			}
++
++			/* too short */
++//			if (get_param->value->used < 2) return HANDLER_GO_ON;
++
++			/* check if it is a number */
++//			start = strtol(get_param->value->ptr, &err, 10);
++			start = strtod(get_param->value->ptr, &err);
++			if (*err != '\0') {
++				return HANDLER_GO_ON;
++			}
++
++//			if (start <= 0) return HANDLER_GO_ON;
++			if (start < 0) return HANDLER_GO_ON;
++
++			/* check if start is > filesize */
++			if (HANDLER_GO_ON != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
++				return HANDLER_GO_ON;
++			}
++
++//			if (start > sce->st.st_size) {
++//				return HANDLER_GO_ON;
++//			}
++
++			/* we are safe now, let's build a h264 header */
++			b = chunkqueue_get_append_buffer(con->write_queue);
++#if 0
++			BUFFER_COPY_STRING_CONST(b, "FLV\x1\x1\0\0\0\x9\0\0\0\x9");
++			http_chunk_append_file(srv, con, con->physical.path, start, sce->st.st_size - start);
++#else
++			{
++			FILE* infile;
++			struct atom_t ftyp_atom;
++			struct atom_t moov_atom;
++			struct atom_t mdat_atom;
++			unsigned char* moov_data = 0;
++			unsigned char* ftyp_data = 0;
++
++			infile = fopen(con->physical.path->ptr, "rb");
++			if(!infile) {
++				return HANDLER_GO_ON;
++			}
++
++			{
++				unsigned int filesize = sce->st.st_size;
++
++				struct atom_t leaf_atom;
++				while(ftell(infile) < filesize)
++				{
++					if(!atom_read_header(infile, &leaf_atom))
++						break;
++
++					atom_print(&leaf_atom);
++
++					if(atom_is(&leaf_atom, "ftyp"))
++					{
++						ftyp_atom = leaf_atom;
++						ftyp_data = malloc(ftyp_atom.size_);
++						fseek(infile, ftyp_atom.start_, SEEK_SET);
++						fread(ftyp_data, ftyp_atom.size_, 1, infile);
++					}
++					else
++					if(atom_is(&leaf_atom, "moov"))
++					{
++						moov_atom = leaf_atom;
++						moov_data = malloc(moov_atom.size_);
++						fseek(infile, moov_atom.start_, SEEK_SET);
++						fread(moov_data, moov_atom.size_, 1, infile);
++					}
++					else
++					if(atom_is(&leaf_atom, "mdat"))
++					{
++						mdat_atom = leaf_atom;
++					}
++					atom_skip(infile, &leaf_atom);
++				}
++			}
++			fclose(infile);
++
++			if(!moov_data)
++				return HANDLER_GO_ON;
++
++			{
++
++			unsigned int mdat_start = (ftyp_data ? ftyp_atom.size_ : 0) + moov_atom.size_;
++			if(!moov_seek(moov_data + ATOM_PREAMBLE_SIZE,
++					moov_atom.size_ - ATOM_PREAMBLE_SIZE,
++					start,
++					&mdat_atom.start_, &mdat_atom.size_,
++					mdat_start - mdat_atom.start_))
++				return HANDLER_GO_ON;
++
++			if(ftyp_data)
++			{
++				buffer_append_memory(b, ftyp_data, ftyp_atom.size_);
++				free(ftyp_data);
++			}
++
++			buffer_append_memory(b, moov_data, moov_atom.size_);
++			free(moov_data);
++
++			{
++			unsigned char mdat_bytes[ATOM_PREAMBLE_SIZE];
++//			mdat_atom.size_ -= bytes_to_skip;
++			atom_write_header(mdat_bytes, &mdat_atom);
++			buffer_append_memory(b, mdat_bytes, ATOM_PREAMBLE_SIZE);
++			b->used++; /* add virtual \0 */
++			}
++
++			http_chunk_append_file(srv, con, con->physical.path, mdat_atom.start_ + ATOM_PREAMBLE_SIZE,
++						mdat_atom.size_ - ATOM_PREAMBLE_SIZE);
++			}
++			}
++#endif
++			response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("video/mp4"));
++
++			con->file_finished = 1;
++
++			return HANDLER_FINISHED;
++		}
++	}
++
++	/* not found */
++	return HANDLER_GO_ON;
++}
++
++/* this function is called at dlopen() time and inits the callbacks */
++
++int mod_h264_streaming_plugin_init(plugin *p) {
++	p->version     = LIGHTTPD_VERSION_ID;
++	p->name        = buffer_init_string("h264_streaming");
++
++	p->init        = mod_h264_streaming_init;
++	p->handle_physical = mod_h264_streaming_path_handler;
++	p->set_defaults  = mod_h264_streaming_set_defaults;
++	p->cleanup     = mod_h264_streaming_free;
++
++	p->data        = NULL;
++
++	return 0;
++}
++
+diff -ur -x '*.m4' -x ltmain.sh -x install-sh -x depcomp -x Makefile.in -x compile -x 'config.*' -x configure -x missing -x mkinstalldirs -x autom4te.cache -Nur -x .svn lighttpd-1.4.18/src/moov.c lighttpd-mod_h264_streaming-1.4.18/src/moov.c
+--- lighttpd-1.4.18/src/moov.c	1970-01-01 03:00:00.000000000 +0300
++++ lighttpd-mod_h264_streaming-1.4.18/src/moov.c	2007-10-23 23:42:37.776980392 +0300
+@@ -0,0 +1,1188 @@
++/******************************************************************************
++ moov.c
++
++ moov - A library for splitting Quicktime/MPEG4 files.
++ http://h264.code-shop.com
++
++ Copyright (C) 2007 CodeShop B.V.
++
++ This program is free software: you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation, either version 3 of the License, or
++ (at your option) any later version.
++
++ This program 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 General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program.  If not, see <http://www.gnu.org/licenses/>.
++******************************************************************************/ 
++
++/* 
++  Uses code snippets from the libquicktime library:
++   http://libquicktime.sourceforge.net
++
++  The QuickTime File Format PDF from Apple:
++    http://developer.apple.com/techpubs/quicktime/qtdevdocs/PDF/QTFileFormat.pdf
++*/
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <limits.h>
++#include <inttypes.h>
++
++static int read_char(unsigned char const* buffer)
++{
++  return buffer[0];
++}
++
++static int read_int32(void const* buffer)
++{
++  unsigned char* p = (unsigned char*)buffer;
++  return (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3];
++}
++
++static void write_int32(void* outbuffer, uint32_t value)
++{
++  unsigned char* p = (unsigned char*)outbuffer;
++  p[0] = (unsigned char)((value >> 24) & 0xff);
++  p[1] = (unsigned char)((value >> 16) & 0xff);
++  p[2] = (unsigned char)((value >> 8) & 0xff);
++  p[3] = (unsigned char)((value >> 0) & 0xff);
++}
++
++struct atom_t
++{
++  unsigned char type_[4];
++  unsigned int size_;
++  unsigned char* start_;
++  unsigned char* end_;
++};
++
++#define ATOM_PREAMBLE_SIZE 8
++
++static unsigned int atom_header_size(unsigned char* atom_bytes)
++{
++  return (atom_bytes[0] << 24) +
++         (atom_bytes[1] << 16) +
++         (atom_bytes[2] << 8) +
++         (atom_bytes[3]);
++}
++
++static unsigned char* atom_read_header(unsigned char* buffer, struct atom_t* atom)
++{
++  atom->start_ = buffer;
++  memcpy(&atom->type_[0], &buffer[4], 4);
++  atom->size_ = atom_header_size(buffer);
++  atom->end_ = atom->start_ + atom->size_;
++
++  return buffer + ATOM_PREAMBLE_SIZE;
++}
++
++static unsigned char* atom_skip(struct atom_t const* atom)
++{
++  return atom->end_;
++}
++
++static int atom_is(struct atom_t const* atom, const char* type)
++{
++  return (atom->type_[0] == type[0] &&
++          atom->type_[1] == type[1] &&
++          atom->type_[2] == type[2] &&
++          atom->type_[3] == type[3])
++         ;
++}
++
++static void atom_print(struct atom_t const* atom)
++{
++  printf("Atom(%c%c%c%c,%d)\n", atom->type_[0], atom->type_[1],
<<Diff was trimmed, longer than 597 lines>>


More information about the pld-cvs-commit mailing list