struct vector * set_manipulate_array(struct vector *arr1, struct vector *arr2, int op) { struct mapping *m; struct vector *r; struct svalue tmp, *v; char *flags; int cnt, res; if (arr1->size < 1 || arr2->size < 1) { switch (op) { case SETARR_SUBTRACT: INCREF(arr1->ref); return arr1; case SETARR_INTERSECT: return allocate_array(0); } } m = make_mapping(arr2, 0); tmp.type = T_NUMBER; tmp.u.number = 1; assign_svalue_no_free(get_map_lvalue(m, &arr2->item[0], 1), &tmp); res = 0; flags = alloca((size_t)arr1->size + 1); for (cnt = 0; cnt < arr1->size; cnt++) { flags[cnt] = 0; v = get_map_lvalue(m, &(arr1->item[cnt]), 0); if (op == SETARR_INTERSECT && v != &const0) { flags[cnt] = 1; res++; } else if (op == SETARR_SUBTRACT && v == &const0) { flags[cnt] = 1; res++; } } r = allocate_array(res); if (res) { for (cnt = res = 0; cnt < arr1->size; cnt++) { if (flags[cnt]) assign_svalue_no_free(&r->item[res++], &arr1->item[cnt]); } } free_mapping(m); return r; }
struct svalue get_variables(struct object *ob) { int i, j; struct vector *names; struct vector *values; struct svalue res; int num_var; if (ob->flags & O_DESTRUCTED) return const0; if (!ob->variables) return const0; num_var = ob->prog->num_variables + ob->prog->inherit[ob->prog->num_inherited - 1] .variable_index_offset; names = allocate_array(num_var); values = allocate_array(num_var); for (j = ob->prog->num_inherited - 1; j >= 0; j--) if (!(ob->prog->inherit[j].type & TYPE_MOD_SECOND) && ob->prog->inherit[j].prog->num_variables > 0) { for (i = 0; i < (int)ob->prog->inherit[j].prog->num_variables; i++) { if (num_var == 0) error("Wrong number of variables in object.\n"); names->item[--num_var].type = T_STRING; names->item[num_var].string_type = STRING_SSTRING; names->item[num_var].u.string = reference_sstring(ob->prog->inherit[j].prog-> variable_names[i].name); assign_svalue_no_free(&values->item[num_var], &ob->variables[ob->prog->inherit[j] .variable_index_offset + i]); } } res.type = T_MAPPING; res.u.map = make_mapping(names, values); free_vector(names); free_vector(values); return res; }
void OTNRTSPStreamer::open_stream_for_client (int client_id) { OTNClient * client = new OTNClient (client_id); make_mapping (client_id, client); client -> start_stream (); }
static ngx_int_t ngx_http_mp4frag_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_chain_t out; u_char *resp_body; ngx_buf_t *resp; char *lastslash; char *mediafilename; u_char *last; size_t root; ngx_str_t path; ngx_str_t index_map = ngx_null_string; const u_char *indexptr; ngx_str_t mediafile_map = ngx_null_string; unsigned medianum, fragnum; uint16_t nmedia; ngx_str_t videocodecdata, audiocodecdata; uint32_t mediaoffset, fragments_offset; uint16_t mediafilenamelen; uint16_t nsamples, nfragments; uint32_t totalsize; unsigned int iii; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } /* discard request body, since we don't need it here */ rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } #if 0 /* set the 'Content-type' header */ r->headers_out.content_type.len = sizeof("text/html") - 1; r->headers_out.content_type.data = (u_char *) "text/html"; #endif last = ngx_http_map_uri_to_path(r, &path, &root, 0); lastslash = strrchr((char*)path.data, '/'); if ( lastslash ) { path.len = lastslash - (char*)path.data; } /* определить путь к файлу индекса и номер фрагмента: */ *lastslash++ = 0; // uri - dirname, lastslash - basename if ( memcmp(lastslash, "Seg1-Frag", 9) != 0 ) { return NGX_HTTP_NOT_FOUND; } fragnum = atoi(lastslash + 9); lastslash = strrchr((char*)path.data, '/'); if ( !lastslash ) { return NGX_HTTP_NOT_FOUND; } medianum = atoi(lastslash + 1); memcpy(lastslash + 1, "index", 6); if ( (rc = make_mapping((const char *)path.data, &index_map, r)) != NGX_OK ) { return rc; } indexptr = index_map.data; #define CHECKMAP(nbytes) do { if (indexptr + nbytes >= index_map.data + index_map.len) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "index underrun, offset 0x%0x", nbytes); goto GENERAL_ERROR;} } while(0) CHECKMAP(10); /* 8 for signature and 2 for media count */ if ( memcmp(index_map.data, "mp4frag", 7) != 0 || index_map.data[7] /* version */ > 2 ) { free_mapping(&index_map); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Bad index format in %s", path.data); goto GENERAL_ERROR; } indexptr += 8; nmedia = get16(indexptr); if ( medianum >= nmedia ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "No media #%d in %s, total %d media", medianum, path.data, nmedia); goto GENERAL_ERROR; } indexptr += 2; CHECKMAP(nmedia * 4); mediaoffset = get32(indexptr + medianum * 4); if ( mediaoffset >= index_map.len ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "short index in %s", path.data); goto GENERAL_ERROR; } indexptr = index_map.data; CHECKMAP(mediaoffset); indexptr = index_map.data + mediaoffset; CHECKMAP(2); mediafilenamelen = get16(indexptr); indexptr += 2; CHECKMAP(mediafilenamelen); if ( index_map.data[7] == 1 ) { if ( (mediafilename = ngx_pcalloc(r->pool, mediafilenamelen + 1)) == NULL ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Insufficient memory"); goto GENERAL_ERROR; } memcpy(mediafilename, (const char *)indexptr, mediafilenamelen); mediafilename[mediafilenamelen] = 0; } else /* index_map.data[7] == 2 */ { mediafilename = (char *)indexptr; } indexptr += mediafilenamelen; CHECKMAP(2); videocodecdata.len = get16(indexptr); indexptr += 2; CHECKMAP(videocodecdata.len); videocodecdata.data = (u_char*)indexptr; indexptr += videocodecdata.len; CHECKMAP(2); audiocodecdata.len = get16(indexptr); indexptr += 2; CHECKMAP(audiocodecdata.len); audiocodecdata.data = (u_char*)indexptr; indexptr += audiocodecdata.len; /* number of fragments in the media */ CHECKMAP(2); nfragments = get16(indexptr); if ( fragnum > nfragments || fragnum < 1 ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "No fragment #%d in media #%d in file %s", fragnum, medianum, path.data); goto NOT_FOUND; } indexptr += 2; CHECKMAP(nfragments * 4); fragments_offset = get32(indexptr + (fragnum - 1) * 4); indexptr = index_map.data; CHECKMAP(fragments_offset); indexptr += fragments_offset; CHECKMAP(6); /* first entry should present anyway */ nsamples = get16(indexptr); if ( nsamples < 1 ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Number of samples is 0 for media #%d, fragment #%d, index %s", medianum, fragnum, path.data); goto GENERAL_ERROR; } /* total fragment size in bytes: */ totalsize = get32(indexptr + 2); ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "nsamples=%d, totalsize=%d", nsamples, totalsize); indexptr += 6; /* allocate memory for response */ if ( (resp_body = ngx_pcalloc(r->pool, totalsize)) == NULL ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Insufficient memory"); goto GENERAL_ERROR; } if ( (resp = ngx_pcalloc(r->pool, sizeof(ngx_buf_t))) == NULL ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Insufficient memory"); goto GENERAL_ERROR; } out.buf = resp; out.next = NULL; resp->pos = resp_body; resp->last = resp_body + totalsize; resp->memory = 1; resp->last_buf = 1; if ( make_mapping(mediafilename, &mediafile_map, r) != NGX_OK ) goto GENERAL_ERROR; /* generate the fragment */ write32(resp_body, totalsize); memcpy(resp_body + 4, "mdat", 4); CHECKMAP(16 * nsamples - 1); /* check if the last byte still inside the index */ /* fragment timestamp is equal to first sample timestamp */ resp_body = write_fragment_prefix(resp_body + 8, &videocodecdata, &audiocodecdata, get32(indexptr + 8)); for ( iii = 0; iii < nsamples; ++iii ) { uint32_t offset = get32(indexptr); uint32_t size = get32(indexptr + 4); uint32_t timestamp = get32(indexptr + 8); uint32_t composition_offset = get24(indexptr + 12); uint8_t flags = indexptr[15]; indexptr += 16; if ( flags ) { resp_body = write_video_packet(resp_body, flags & 2, 0, composition_offset, timestamp, mediafile_map.data + offset, size); } else { resp_body = write_audio_packet(resp_body, 0, timestamp, mediafile_map.data + offset, size); } } free_mapping(&index_map); free_mapping(&mediafile_map); if ( resp_body != resp->last ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "response buffer overrun"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = totalsize; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only || r->method == NGX_HTTP_HEAD) { return rc; } /* send the buffer chain of your response */ return ngx_http_output_filter(r, &out); GENERAL_ERROR: free_mapping(&index_map); free_mapping(&mediafile_map); return NGX_HTTP_INTERNAL_SERVER_ERROR; NOT_FOUND: free_mapping(&index_map); free_mapping(&mediafile_map); return NGX_HTTP_NOT_FOUND; }
static ngx_int_t ngx_http_f4fhds_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_chain_t out; u_char *resp_body; ngx_buf_t *resp; char *lastslash; char *segsuffix; size_t root; ngx_str_t path; ngx_str_t index_map = ngx_null_string; ngx_str_t mediafile_map = ngx_null_string; unsigned fragnum; uint32_t totalsize; ngx_table_elt_t *self; unsigned afraentries; unsigned g_afraentries, g_entry_size = 0; unsigned globaltable_offset; unsigned long long afraoffset = 0, offsetfromafra = 0; unsigned entryindex = 0; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } if ( (rc = ngx_http_discard_request_body(r)) != NGX_OK ) { return rc; } if ( (self = ngx_list_push(&r->headers_out.headers)) == NULL ) { ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "Insufficient memory for ngx_list_push"); return NGX_ERROR; } self->hash = 1; ngx_str_set(&self->key, "X-Inventos-F4FHDS-Version"); ngx_str_set(&self->value, VERSION); ngx_http_map_uri_to_path(r, &path, &root, 0); ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "path=%s", path.data); lastslash = strrchr((char*)path.data, '/'); ++lastslash; segsuffix = (char *)memmem(lastslash, path.len - (lastslash - (char *)path.data), "Seg1-Frag", 9); if ( segsuffix == NULL ) { return NGX_HTTP_NOT_FOUND; } segsuffix += 4; /* "Seg1" */ fragnum = atoi(segsuffix + /* "-Frag" */ 5); if ( fragnum < 1 ) { return NGX_HTTP_NOT_FOUND; } memcpy(segsuffix, ".f4x", 4); path.len = segsuffix - (char*)path.data + 4; segsuffix[4] = 0; ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "f4x_path=%s", path.data); if ( (rc = make_mapping((const char *)path.data, &index_map, r)) != NGX_OK ) { return rc; } if ( index_map.len < 8 ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Wrong f4x afra size: %d in %s", index_map.len, path.data); goto GENERAL_ERROR; } if ( memcmp(index_map.data + 4, "afra", 4) != 0 ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Wrong f4x format: %s", path.data); goto GENERAL_ERROR; } if ( getboxlen(index_map.data) != index_map.len ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Wrong f4x prefix size: %d in %s", get32(index_map.data), path.data); goto GENERAL_ERROR; } if ( (index_map.data[12] & 0x20) == 0 ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Global entries are not present in %s", path.data); goto GENERAL_ERROR; } afraentries = get32(index_map.data + 17); globaltable_offset = 17 + 4 + afraentries * (8 /* time */ + ((index_map.data[12] & 0x40) ? 8 : 4)) + 4; if ( index_map.len < globaltable_offset ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Index file too short: %s", path.data); goto GENERAL_ERROR; } g_afraentries = get32(index_map.data + globaltable_offset - 4); switch ( index_map.data[12] & 0xc0 ) { case 0xc0: g_entry_size = 32; break; case 0x80: g_entry_size = 24; break; case 0x40: g_entry_size = 28; break; case 0: g_entry_size = 20; break; } ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "globaltable_offset=%d, afraentries=%d, g_afraentries=%d, entrysize=%d", globaltable_offset, afraentries, g_afraentries, g_entry_size ); if ( index_map.len < globaltable_offset + g_afraentries * g_entry_size ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Index file too short: %s, len=%d, need=%d, globaltable_offset=%d, afraentries=%d, g_afraentries=%d, entrysize=%d", path.data, index_map.len, globaltable_offset + g_afraentries * g_entry_size, globaltable_offset, afraentries, g_afraentries, g_entry_size ); goto GENERAL_ERROR; } #define FIND_SEGMENT(SEGSIZE, FRAGSIZE, AOSIZE, OFASIZE) \ for ( entryindex = 0; entryindex < g_afraentries; ++entryindex ) { \ u_char *pentry = index_map.data + globaltable_offset + entryindex * g_entry_size; \ unsigned segment = get##SEGSIZE (pentry + 8); \ unsigned fragment = get##FRAGSIZE (pentry + 8 + SEGSIZE/8); \ if ( segment == 1 && fragment == fragnum ) { \ afraoffset = get##AOSIZE (pentry + 8 + SEGSIZE/8 + FRAGSIZE/8); \ offsetfromafra = get##OFASIZE (pentry + 8 + SEGSIZE/8 + FRAGSIZE/8 + AOSIZE/8); \ break; \ } \ } switch ( index_map.data[12] & 0xc0 ) { case 0xc0: FIND_SEGMENT(32, 32, 64, 64); break; case 0x80: FIND_SEGMENT(32, 32, 32, 32); break; case 0x40: FIND_SEGMENT(16, 16, 64, 64); break; case 0: FIND_SEGMENT(16, 16, 32, 32); break; } if ( entryindex == g_afraentries ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Fragment #%d not found in %s, g_afraentries=%d", fragnum, path.data, g_afraentries); goto NOT_FOUND; } if ( offsetfromafra != 0 ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "OffsetFromAfra=%llu not supported, %s", offsetfromafra, path.data); goto GENERAL_ERROR; } memcpy(segsuffix, ".f4f", 4); if ( (rc = make_mapping((const char *)path.data, &mediafile_map, r)) != NGX_OK ) { return rc; } if ( mediafile_map.len < afraoffset + 8 ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Mediafile is too short: %s", path.data); goto GENERAL_ERROR; } { const u_char *afra = mediafile_map.data + afraoffset; unsigned long long afralen = getboxlen(afra); const u_char *abst = afra + afralen; unsigned long long abstlen = getboxlen(abst); const u_char *moof = abst + abstlen; unsigned long long mooflen = getboxlen(moof); const u_char *mdat = moof + mooflen; unsigned long long mdatlen = getboxlen(mdat); totalsize = afralen + abstlen + mooflen + mdatlen; if ( (resp_body = ngx_pcalloc(r->pool, totalsize)) == NULL ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Insufficient memory"); goto GENERAL_ERROR; } memcpy(resp_body, afra, totalsize); } if ( (resp = ngx_pcalloc(r->pool, sizeof(ngx_buf_t))) == NULL ) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Insufficient memory"); goto GENERAL_ERROR; } out.buf = resp; out.next = NULL; resp->pos = resp_body; resp->last = resp_body + totalsize; resp->memory = 1; resp->last_buf = 1; free_mapping(&index_map); free_mapping(&mediafile_map); r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = totalsize; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only || r->method == NGX_HTTP_HEAD) { return rc; } return ngx_http_output_filter(r, &out); GENERAL_ERROR: free_mapping(&index_map); free_mapping(&mediafile_map); return NGX_HTTP_INTERNAL_SERVER_ERROR; NOT_FOUND: free_mapping(&index_map); free_mapping(&mediafile_map); return NGX_HTTP_NOT_FOUND; }