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>> _______________________________________________ pld-cvs-commit mailing list [email protected] http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit
