Author: glen Date: Mon Jan 26 19:09:54 2009 GMT Module: SOURCES Tag: HEAD ---- Log message: - updated to version 2
---- Files affected: SOURCES: lighttpd-mod_h264_streaming.patch (1.1 -> 1.2) ---- Diffs: ================================================================ Index: SOURCES/lighttpd-mod_h264_streaming.patch diff -u SOURCES/lighttpd-mod_h264_streaming.patch:1.1 SOURCES/lighttpd-mod_h264_streaming.patch:1.2 --- SOURCES/lighttpd-mod_h264_streaming.patch:1.1 Tue Oct 23 22:48:42 2007 +++ SOURCES/lighttpd-mod_h264_streaming.patch Mon Jan 26 20:09:48 2009 @@ -1,4 +1,3 @@ -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 @@ @@ -13,30 +12,16 @@ 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 @@ +--- /dev/null 2008-11-04 20:33:38.146691408 +0200 ++++ lighttpd-1.4.18/src/mod_h264_streaming.c 2009-01-26 20:59:51.385271731 +0200 +@@ -0,0 +1,337 @@ +/******************************************************************************* + 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/>. ++ Copyright (C) 2007-2009 CodeShop B.V. +******************************************************************************/ + +#include <ctype.h> @@ -57,463 +42,357 @@ +#include "config.h" +#endif + ++#include "moov.h" ++ +/* plugin config for all request/connections */ + +typedef struct { -+ array *extensions; ++ array *extensions; +} plugin_config; + +typedef struct { -+ PLUGIN_DATA; ++ PLUGIN_DATA; + -+ buffer *query_str; -+ array *get_params; ++ buffer *query_str; ++ array *get_params; + -+ plugin_config **config_storage; ++ plugin_config **config_storage; + -+ plugin_config conf; ++ plugin_config conf; +} plugin_data; + +/* init the plugin data */ +INIT_FUNC(mod_h264_streaming_init) { -+ plugin_data *p; ++ plugin_data *p; + -+ p = calloc(1, sizeof(*p)); ++ p = calloc(1, sizeof(*p)); + -+ p->query_str = buffer_init(); -+ p->get_params = array_init(); ++ p->query_str = buffer_init(); ++ p->get_params = array_init(); + -+ return p; ++ return p; +} + +/* detroy the plugin data */ +FREE_FUNC(mod_h264_streaming_free) { -+ plugin_data *p = p_d; ++ plugin_data *p = p_d; + -+ UNUSED(srv); ++ UNUSED(srv); + -+ if (!p) return HANDLER_GO_ON; ++ if (!p) return HANDLER_GO_ON; + -+ if (p->config_storage) { -+ size_t i; ++ if (p->config_storage) { ++ size_t i; + -+ for (i = 0; i < srv->config_context->used; i++) { -+ plugin_config *s = p->config_storage[i]; ++ for (i = 0; i < srv->config_context->used; i++) { ++ plugin_config *s = p->config_storage[i]; + -+ if (!s) continue; ++ if (!s) continue; + -+ array_free(s->extensions); ++ array_free(s->extensions); + -+ free(s); -+ } -+ free(p->config_storage); -+ } ++ free(s); ++ } ++ free(p->config_storage); ++ } + -+ buffer_free(p->query_str); -+ array_free(p->get_params); ++ buffer_free(p->query_str); ++ array_free(p->get_params); + -+ free(p); ++ free(p); + -+ return HANDLER_GO_ON; ++ 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; ++ 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 } -+ }; ++ 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; ++ if (!p) return HANDLER_ERROR; + -+ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *)); ++ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *)); + -+ for (i = 0; i < srv->config_context->used; i++) { -+ plugin_config *s; ++ for (i = 0; i < srv->config_context->used; i++) { ++ plugin_config *s; + -+ s = calloc(1, sizeof(plugin_config)); -+ s->extensions = array_init(); ++ s = calloc(1, sizeof(plugin_config)); ++ s->extensions = array_init(); + -+ cv[0].destination = s->extensions; ++ cv[0].destination = s->extensions; + -+ p->config_storage[i] = s; ++ p->config_storage[i] = s; + -+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) { -+ return HANDLER_ERROR; -+ } -+ } ++ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) { ++ return HANDLER_ERROR; ++ } ++ } + -+ return HANDLER_GO_ON; ++ return HANDLER_GO_ON; +} + +#define PATCH(x) \ -+ p->conf.x = s->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); ++ size_t i, j; ++ plugin_config *s = p->config_storage[0]; + -+ /* 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); -+ } -+ } -+ } ++ 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; ++ /* 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]; + -+ key = qrystr->ptr; ++ /* condition didn't match */ ++ if (!config_check_cond(srv, con, dc)) continue; + -+ /* we need the \0 */ -+ for (i = 0; i < qrystr->used; i++) { -+ switch(qrystr->ptr[i]) { -+ case '=': -+ if (is_key) { -+ val = qrystr->ptr + i + 1; ++ /* merge config */ ++ for (j = 0; j < dc->value->used; j++) { ++ data_unset *du = dc->value->data[j]; + -+ qrystr->ptr[i] = '\0'; ++ if (buffer_is_equal_string(du->key, CONST_STR_LEN("h264-streaming.extensions"))) { ++ PATCH(extensions); ++ } ++ } ++ } + -+ is_key = 0; -+ } ++ return 0; ++} ++#undef PATCH + -+ break; -+ case '&': -+ case '\0': /* fin symbol */ -+ if (!is_key) { -+ data_string *ds; -+ /* we need at least a = since the last & */ ++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; + -+ /* terminate the value */ -+ qrystr->ptr[i] = '\0'; ++ 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)); ++ is_key = 0; ++ } + -+ array_insert_unique(get_params, (data_unset *)ds); -+ } ++ break; ++ case '&': ++ case '\0': /* fin symbol */ ++ if (!is_key) { ++ data_string *ds; ++ /* we need at least a = since the last & */ + -+ key = qrystr->ptr + i + 1; -+ val = NULL; -+ is_key = 1; -+ break; -+ } -+ } ++ /* terminate the value */ ++ qrystr->ptr[i] = '\0'; + -+ return 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)); + -+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); ++ array_insert_unique(get_params, (data_unset *)ds); ++ } + -+void write_char(unsigned char* outbuffer, int value) -+{ -+ outbuffer[0] = (unsigned char)(value); -+} ++ key = qrystr->ptr + i + 1; ++ val = NULL; ++ is_key = 1; ++ break; ++ } ++ } + -+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); ++ return 0; +} + -+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]); -+} ++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; ++ double start = 0.0; ++ double end = 0.0; ++ char *err = NULL; ++ int client_is_flash = 0; ++ ++ 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 there is a start=[0-9]+ in the header use it as start, ++ * otherwise send the full file */ ++ if (NULL != (get_param = (data_string *)array_get_element(p->get_params, "start"))) ++ { ++ /* check if it is a number */ ++ start = strtod(get_param->value->ptr, &err); ++ if (*err != '\0') { ++ return HANDLER_GO_ON; ++ } ++ if (start < 0) return HANDLER_GO_ON; ++ } + -+int atom_read_header(FILE* infile, struct atom_t* atom) -+{ -+ unsigned char atom_bytes[ATOM_PREAMBLE_SIZE]; ++ /* if there is an end=[0-9]+ in the header use it as end */ ++ if (NULL != (get_param = (data_string *)array_get_element(p->get_params, "end"))) ++ { ++ /* check if it is a number */ ++ end = strtod(get_param->value->ptr, &err); ++ if (*err != '\0') { ++ return HANDLER_GO_ON; ++ } ++ if (end < 0 || start >= end) return HANDLER_GO_ON; ++ } + -+ atom->start_ = ftell(infile); ++ if (NULL != (get_param = (data_string *)array_get_element(p->get_params, "client"))) ++ { ++ client_is_flash = starts_with(get_param->value->ptr, "FLASH"); ++ } + -+ 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_; ++ /* get file info */ ++ if (HANDLER_GO_ON != stat_cache_get_entry(srv, con, con->physical.path, &sce)) { ++ return HANDLER_GO_ON; ++ } + -+ return 1; -+} ++ /* we are safe now, let's build a h264 header */ ++ { ++ { ++ unsigned int filesize = sce->st.st_size; + -+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]); -+} ++ void* mp4_header; ++ uint32_t mp4_header_size; ++ uint64_t mdat_offset; ++ uint64_t mdat_size; ++ ++ int result = mp4_split(con->physical.path->ptr, filesize, start, end, ++ &mp4_header, &mp4_header_size, ++ &mdat_offset, &mdat_size, client_is_flash); + -+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]) -+ ; -+} ++ if(result) ++ { ++ buffer* b = chunkqueue_get_append_buffer(con->write_queue); ++ buffer_append_memory(b, mp4_header, mp4_header_size); ++ b->used++; /* add virtual \0 */ + -+void atom_skip(FILE* infile, struct atom_t const* atom) -+{ -+ fseek(infile, atom->end_, SEEK_SET); -+} ++ http_chunk_append_file(srv, con, con->physical.path, ++ mdat_offset, mdat_size); ++ } + -+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_); -+} ++ if(mp4_header) ++ { ++ free(mp4_header); ++ } + ++ if(!result) ++ { ++ return HANDLER_GO_ON; ++ } ++ } ++ } + -+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")) -+ { <<Diff was trimmed, longer than 597 lines>> ---- CVS-web: http://cvs.pld-linux.org/cgi-bin/cvsweb.cgi/SOURCES/lighttpd-mod_h264_streaming.patch?r1=1.1&r2=1.2&f=u _______________________________________________ pld-cvs-commit mailing list [email protected] http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit
