MONGO_EXPORT int bson_append_bson( bson *b, const char *name, const bson *bson ) {
    if ( !bson ) return BSON_ERROR;
    if ( bson_append_estart( b, BSON_OBJECT, name, bson_size( bson ) ) == BSON_ERROR )
        return BSON_ERROR;
    bson_append( b , bson->data , bson_size( bson ) );
    return BSON_OK;
}


MONGO_EXPORT bson_type bson_iterator_next( bson_iterator *i ) {
    size_t ds;

    if ( i->first ) {
        i->first = 0;
        return ( bson_type )( *i->cur );
    }

    switch ( bson_iterator_type( i ) ) {
    case BSON_EOO:
        return BSON_EOO; /* don't advance */
    case BSON_UNDEFINED:
    case BSON_NULL:
        ds = 0;
        break;
    case BSON_BOOL:
        ds = 1;
        break;
    case BSON_INT:
        ds = 4;
        break;
    case BSON_LONG:
    case BSON_DOUBLE:
    case BSON_TIMESTAMP:
    case BSON_DATE:
        ds = 8;
        break;
    case BSON_OID:
        ds = 12;
        break;
    case BSON_STRING:
    case BSON_SYMBOL:
    case BSON_CODE:
        ds = 4 + bson_iterator_int_raw( i );
        break;
    case BSON_BINDATA:
        ds = 5 + bson_iterator_int_raw( i );
        break;
    case BSON_OBJECT:
    case BSON_ARRAY:
    case BSON_CODEWSCOPE:
        ds = bson_iterator_int_raw( i );
        break;
    case BSON_DBREF:
        ds = 4+12 + bson_iterator_int_raw( i );
        break;
    case BSON_REGEX: {
        const char *s = bson_iterator_value( i );
        const char *p = s;
        p += strlen( p )+1;
        p += strlen( p )+1;
        ds = p-s;
        break;
    }

    default: {
        char msg[] = "unknown type: 000000000000";
        bson_numstr( msg+14, ( unsigned )( i->cur[0] ) );
        bson_fatal_msg( 0, msg );
        return 0;
    }
    }

    i->cur += 1 + strlen( i->cur + 1 ) + 1 + ds;

    return ( bson_type )( *i->cur );
}


static void bson_append( bson *b, const void *data, size_t len ) {
    memcpy( b->cur , data , len );
    b->cur += len;
}


static int mongo_cursor_get_more( mongo_cursor *cursor ) {
    int res;

    if( cursor->limit > 0 && cursor->seen >= cursor->limit ) {
        cursor->err = MONGO_CURSOR_EXHAUSTED;
        return MONGO_ERROR;
    }
    else if( ! cursor->reply ) {
        cursor->err = MONGO_CURSOR_INVALID;
        return MONGO_ERROR;
    }
    else if( ! cursor->reply->fields.cursorID ) {
        cursor->err = MONGO_CURSOR_EXHAUSTED;
        return MONGO_ERROR;
    }
    else {
        char *data;
        size_t sl = strlen( cursor->ns )+1;
        int limit = 0;
        mongo_message *mm;

        if( cursor->limit > 0 )
            limit = cursor->limit - cursor->seen;

        mm = mongo_message_create( 16 /*header*/
                                   +4 /*ZERO*/
                                   +sl
                                   +4 /*numToReturn*/
                                   +8 /*cursorID*/
                                   , 0, 0, MONGO_OP_GET_MORE );
        data = &mm->data;
        data = mongo_data_append32( data, &ZERO );
        data = mongo_data_append( data, cursor->ns, sl );
        data = mongo_data_append32( data, &limit );
        mongo_data_append64( data, &cursor->reply->fields.cursorID );

        bson_free( cursor->reply );
        res = mongo_message_send( cursor->conn, mm );
        if( res != MONGO_OK ) {
            mongo_cursor_destroy( cursor );
            return MONGO_ERROR;
        }

        res = mongo_read_response( cursor->conn, &( cursor->reply ) );
        if( res != MONGO_OK ) {
            mongo_cursor_destroy( cursor );
            return MONGO_ERROR;
        }
        cursor->current.data = NULL;
        cursor->seen += cursor->reply->fields.num;

        return MONGO_OK;
    }
}


MONGO_EXPORT int mongo_create_capped_collection( mongo *conn, const char *db,
        const char *collection, int size, int max, bson *out ) {

    bson b;
    int result;

    bson_init( &b );
    bson_append_string( &b, "create", collection );
    bson_append_bool( &b, "capped", 1 );
    bson_append_int( &b, "size", size );
    if( max > 0 )
        bson_append_int( &b, "max", size );
    bson_finish( &b );

    result = mongo_run_command( conn, db, &b, out );

    bson_destroy( &b );

    return result;
}


MONGO_EXPORT int mongo_check_connection( mongo *conn ) {
    if( ! conn->connected )
        return MONGO_ERROR;

    if( mongo_simple_int_command( conn, "admin", "ping", 1, NULL ) == MONGO_OK )
        return MONGO_OK;
    else
        return MONGO_ERROR;
}


MONGO_EXPORT mongo* mongo_create( void ) {
    return (mongo*)bson_malloc(sizeof(mongo));
}


int bson_check_field_name( bson *b, const char *string,
                           const size_t length ) {

    return bson_validate_string( b, ( const unsigned char * )string, length, 1, 1, 1 );
}


MONGO_EXPORT void mongo_replica_set_add_seed( mongo *conn, const char *host, int port ) {
    mongo_replica_set_add_node( &conn->replica_set->seeds, host, port );
}


void bson_builder_error( bson *b ) {
    if( err_handler )
        err_handler( "BSON error." );
}


static int bson_append_string_base( bson *b, const char *name,
                                    const char *value, size_t len, bson_type type ) {

    size_t sl = len + 1;
    if ( bson_check_string( b, ( const char * )value, sl - 1 ) == BSON_ERROR )
        return BSON_ERROR;
    if ( bson_append_estart( b, type, name, 4 + sl ) == BSON_ERROR ) {
        return BSON_ERROR;
    }
    bson_append32_as_int( b , ( int )sl );
    bson_append( b , value , sl - 1 );
    bson_append( b , "\0" , 1 );
    return BSON_OK;
}


bson_bool_t gridfile_get_boolean( gridfile *gfile, const char *name ) {
    bson_iterator it;

    bson_find( &it, gfile->meta, name );
    return bson_iterator_bool( &it );
}


MONGO_EXPORT void mongo_replset_add_seed( mongo *conn, const char *host, int port ) {
    bson_errprintf("WARNING: mongo_replset_add_seed() is deprecated, please use mongo_replica_set_add_seed()\n");
    mongo_replica_set_add_node( &conn->replica_set->seeds, host, port );
}


MONGO_EXPORT const char *gridfile_get_md5( gridfile *gfile ) {
    bson_iterator it;

    bson_find( &it, gfile->meta, "md5" );
    return bson_iterator_string( &it );
}


MONGO_EXPORT int mongo_client( mongo *conn , const char *host, int port ) {
    mongo_init( conn );

    conn->primary = bson_malloc( sizeof( mongo_host_port ) );
    strncpy( conn->primary->host, host, strlen( host ) + 1 );
    conn->primary->port = port;
    conn->primary->next = NULL;

    if( mongo_env_socket_connect( conn, host, port ) != MONGO_OK )
        return MONGO_ERROR;

    if( mongo_check_is_master( conn ) != MONGO_OK )
        return MONGO_ERROR;
    else
        return MONGO_OK;
}


MONGO_EXPORT bson_bool_t mongo_create_simple_index( mongo *conn, const char *ns, const char *field, int options, bson *out ) {
    bson b;
    bson_bool_t success;

    bson_init( &b );
    bson_append_int( &b, field, 1 );
    bson_finish( &b );

    success = mongo_create_index( conn, ns, &b, options, out );
    bson_destroy( &b );
    return success;
}


MONGO_EXPORT bson_err_handler set_bson_err_handler( bson_err_handler func ) {
    bson_err_handler old = err_handler;
    err_handler = func;
    return old;
}


static int mongo_cursor_bson_valid( mongo_cursor *cursor, const bson *bson ) {
    if( ! bson->finished ) {
        cursor->err = MONGO_CURSOR_BSON_ERROR;
        cursor->conn->err = MONGO_BSON_NOT_FINISHED;
        return MONGO_ERROR;
    }

    if( bson->err & BSON_NOT_UTF8 ) {
        cursor->err = MONGO_CURSOR_BSON_ERROR;
        cursor->conn->err = MONGO_BSON_INVALID;
        return MONGO_ERROR;
    }

    return MONGO_OK;
}


MONGO_EXPORT int  mongo_get_server_err(mongo* conn) {
    return conn->lasterrcode;
}


MONGO_EXPORT int bson_append_symbol_n( bson *b, const char *name, const char *value, size_t len ) {
    return bson_append_string_base( b, name, value, len, BSON_SYMBOL );
}


int mongo_env_socket_connect( mongo *conn, const char *host, int port ) {
    char port_str[NI_MAXSERV];
    int status;

    struct addrinfo ai_hints;
    struct addrinfo *ai_list = NULL;
    struct addrinfo *ai_ptr = NULL;

    if ( port < 0 ) {
        return mongo_env_unix_socket_connect( conn, host );
    }

    conn->sock = 0;
    conn->connected = 0;
    sprintf(port_str,"%d",port);

    bson_sprintf( port_str, "%d", port );

    memset( &ai_hints, 0, sizeof( ai_hints ) );
#ifdef AI_ADDRCONFIG
    ai_hints.ai_flags = AI_ADDRCONFIG;
#endif
    ai_hints.ai_family = AF_UNSPEC;
    ai_hints.ai_socktype = SOCK_STREAM;

    status = getaddrinfo( host, port_str, &ai_hints, &ai_list );
    if ( status != 0 ) {
        bson_errprintf( "getaddrinfo failed: %s", gai_strerror( status ) );
        conn->err = MONGO_CONN_ADDR_FAIL;
        return MONGO_ERROR;
    }

    for ( ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next ) {
        conn->sock = socket( ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol );
        if ( conn->sock < 0 ) {
            conn->sock = 0;
            continue;
        }

        status = connect( conn->sock, ai_ptr->ai_addr, ai_ptr->ai_addrlen );
        if ( status != 0 ) {
            mongo_env_close_socket( conn->sock );
            conn->sock = 0;
            continue;
        }
#if __APPLE__
        {
            int flag = 1;
            setsockopt( conn->sock, SOL_SOCKET, SO_NOSIGPIPE,
                       ( void * ) &flag, sizeof( flag ) );
        }
#endif

        if ( ai_ptr->ai_protocol == IPPROTO_TCP ) {
            int flag = 1;

            setsockopt( conn->sock, IPPROTO_TCP, TCP_NODELAY,
                        ( void * ) &flag, sizeof( flag ) );
            if ( conn->op_timeout_ms > 0 )
                mongo_env_set_socket_op_timeout( conn, conn->op_timeout_ms );
        }

        conn->connected = 1;
        break;
    }

    freeaddrinfo( ai_list );

    if ( ! conn->connected ) {
        conn->err = MONGO_CONN_FAIL;
        return MONGO_ERROR;
    }

    return MONGO_OK;
}


explicit VarIsInitializedOp(OpKernelConstruction* c) : OpKernel(c) {}


ReadVariablesOp::ReadVariablesOp(OpKernelConstruction* c) : OpKernel(c) {
  int n;
  OP_REQUIRES_OK(c, c->GetAttr("N", &n));
  OP_REQUIRES_OK(c, c->GetAttr("dtypes", &dtypes_));
  OP_REQUIRES(c, n == dtypes_.size(),
              errors::InvalidArgument(
                  "Mismatched number of arguments to ReadVariablesOp (", n,
                  " vs. ", dtypes_.size(), ")"));
}


  void Compute(OpKernelContext* context) override {
    OP_REQUIRES(context, dtype_ == context->input(1).dtype(),
                errors::InvalidArgument(
                    "Variable and value dtypes don't match; respectively, ",
                    DataTypeString(dtype_), " and ",
                    DataTypeString(context->input(1).dtype())));
    core::RefCountPtr<Var> variable;
    const Tensor& value = context->input(1);
    // Note: every resource-variable-manipulating op assumes copy-on-write
    // semantics, and creates a copy of the variable's Tensor if its refcount is
    // bigger than 1 when we try to modify it. This means we never need to copy
    // the original tensor for AssignVariableOp; even if there are other live
    // users of it we know none can modify it so this is always safe (even in
    // esoteric cases where the same tensor is used to initialize multiple
    // variables or the tensor is a constant this is safe, as future writes will
    // trigger copies).
    OP_REQUIRES_OK(context, LookupOrCreateResource<Var>(
                                context, HandleFromInput(context, 0), &variable,
                                [this, &value](Var** ptr) {
                                  *ptr = new Var(dtype_);
                                  *(*ptr)->tensor() = value;
                                  (*ptr)->is_initialized = true;
                                  return Status::OK();
                                }));
    mutex_lock ml(*variable->mu());
    // (variable->tensor()->dtype() == DT_INVALID && !variable->is_initialized)
    // check below is to allow an XLA specific situation wherein update can
    // happen first by the AssignVariableOp,
    // in which case the variable is still uninitialized.
    // When using TF-XLA, this scenario is possible when the execution uses the
    // 'fallback' path (which essentially invokes Tensorflow ops via
    // partitioned_call).
    OP_REQUIRES(context,
                (variable->tensor()->dtype() == DT_INVALID &&
                 !variable->is_initialized) ||
                    variable->tensor()->dtype() == dtype_,
                errors::InvalidArgument(
                    "Trying to assign variable with wrong dtype. Expected ",
                    DataTypeString(variable->tensor()->dtype()), " got ",
                    DataTypeString(dtype_)));
    if (variable->copy_on_read_mode.load()) {
      AllocatorAttributes attr;
      attr.set_gpu_compatible(true);
      attr.set_nic_compatible(true);
      OP_REQUIRES_OK(context,
                     context->allocate_temp(value.dtype(), value.shape(),
                                            variable->tensor(), attr));
      functor::DenseUpdate<Device, T, ASSIGN> copy_functor;
      copy_functor(context->eigen_device<Device>(),
                   variable->tensor()->flat<T>(), value.flat<T>());
    } else {
      *variable->tensor() = value;
    }
    variable->is_initialized = true;
  }


static int decode_bdlt(GetByteContext *gb, uint8_t *frame, int width, int height)
{
    uint8_t *line_ptr;
    int count, lines, segments;

    count = bytestream2_get_le16(gb);
    if (count >= height)
        return AVERROR_INVALIDDATA;
    frame += width * count;
    lines = bytestream2_get_le16(gb);
    if (count + lines > height)
        return AVERROR_INVALIDDATA;

    while (lines--) {
        if (bytestream2_get_bytes_left(gb) < 1)
            return AVERROR_INVALIDDATA;
        line_ptr = frame;
        frame += width;
        segments = bytestream2_get_byteu(gb);
        while (segments--) {
            if (frame - line_ptr <= bytestream2_peek_byte(gb))
                return AVERROR_INVALIDDATA;
            line_ptr += bytestream2_get_byte(gb);
            count = (int8_t)bytestream2_get_byte(gb);
            if (count >= 0) {
                if (frame - line_ptr < count)
                    return AVERROR_INVALIDDATA;
                if (bytestream2_get_buffer(gb, line_ptr, count) != count)
                    return AVERROR_INVALIDDATA;
            } else {
                count = -count;
                if (frame - line_ptr < count)
                    return AVERROR_INVALIDDATA;
                memset(line_ptr, bytestream2_get_byte(gb), count);
            }
            line_ptr += count;
        }
    }

    return 0;
}


static void copy_asoundrc(void) {
	// copy XAUTHORITY_FILE in the new home directory
	char *src = RUN_ASOUNDRC_FILE ;
	char *dest;
	if (asprintf(&dest, "%s/.asoundrc", cfg.homedir) == -1)
		errExit("asprintf");

	// if destination is a symbolic link, exit the sandbox!!!
	if (is_link(dest)) {
		fprintf(stderr, "Error: %s is a symbolic link\n", dest);
		exit(1);
	}

	copy_file_as_user(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR); // regular user
	fs_logger2("clone", dest);

	// delete the temporary file
	unlink(src);
}


const char *gnu_basename(const char *path)
{
	const char *last_slash = strrchr(path, '/');
	if (!last_slash)
		return path;
	return last_slash+1;
}


void fs_private_homedir(void) {
	char *homedir = cfg.homedir;
	char *private_homedir = cfg.home_private;
	assert(homedir);
	assert(private_homedir);

	int xflag = store_xauthority();
	int aflag = store_asoundrc();

	uid_t u = getuid();
	gid_t g = getgid();
	struct stat s;
	if (stat(homedir, &s) == -1) {
		fprintf(stderr, "Error: cannot find user home directory\n");
		exit(1);
	}

	// mount bind private_homedir on top of homedir
	if (arg_debug)
		printf("Mount-bind %s on top of %s\n", private_homedir, homedir);
	if (mount(private_homedir, homedir, NULL, MS_BIND|MS_REC, NULL) < 0)
		errExit("mount bind");
	fs_logger3("mount-bind", private_homedir, cfg.homedir);
// preserve mode and ownership
//	if (chown(homedir, s.st_uid, s.st_gid) == -1)
//		errExit("mount-bind chown");
//	if (chmod(homedir, s.st_mode) == -1)
//		errExit("mount-bind chmod");

	if (u != 0) {
		// mask /root
		if (arg_debug)
			printf("Mounting a new /root directory\n");
		if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC,  "mode=700,gid=0") < 0)
			errExit("mounting home directory");
		fs_logger("mount tmpfs on /root");
	}
	else {
		// mask /home
		if (arg_debug)
			printf("Mounting a new /home directory\n");
		if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC,  "mode=755,gid=0") < 0)
			errExit("mounting home directory");
		fs_logger("mount tmpfs on /home");
	}

	skel(homedir, u, g);
	if (xflag)
		copy_xauthority();
	if (aflag)
		copy_asoundrc();
}


static void Np_toPrecision(js_State *J)
{
	js_Object *self = js_toobject(J, 0);
	int width = js_tointeger(J, 1);
	char buf[32];
	double x;
	if (self->type != JS_CNUMBER) js_typeerror(J, "not a number");
	if (width < 1) js_rangeerror(J, "precision %d out of range", width);
	if (width > 21) js_rangeerror(J, "precision %d out of range", width);
	x = self->u.number;
	if (isnan(x) || isinf(x))
		js_pushstring(J, jsV_numbertostring(J, buf, x));
	else
		numtostr(J, "%.*g", width, self->u.number);
}


GF_Err Media_FindSyncSample(GF_SampleTableBox *stbl, u32 searchFromSample, u32 *sampleNumber, u8 mode)
{
	GF_ISOSAPType isRAP;
	u32 next, prev, next_in_sap, prev_in_sap;
	if (!stbl || !stbl->SyncSample) return GF_BAD_PARAM;

	//set to current sample if we don't find a RAP
	*sampleNumber = searchFromSample;

	//this is not the exact sample, but the prev move to next sample if enough samples....
	if ( (mode == GF_ISOM_SEARCH_SYNC_FORWARD) && (searchFromSample == stbl->SampleSize->sampleCount) ) {
		return GF_OK;
	}
	if ( (mode == GF_ISOM_SEARCH_SYNC_BACKWARD) && !searchFromSample) {
		*sampleNumber = 1;
		return GF_OK;
	}
	//get the entry
	stbl_GetSampleRAP(stbl->SyncSample, searchFromSample, &isRAP, &prev, &next);
	if (isRAP) {
		(*sampleNumber) = searchFromSample;
		return GF_OK;
	}

	/*check sample groups - prev & next are overwritten if RAP group is found, but are not re-initialized otherwise*/
	stbl_SearchSAPs(stbl, searchFromSample, &isRAP, &prev_in_sap, &next_in_sap);
	if (isRAP) {
		(*sampleNumber) = searchFromSample;
		return GF_OK;
	}

	if (prev_in_sap > prev)
		prev = prev_in_sap;
	if (next_in_sap && next_in_sap < next)
		next = next_in_sap;

	//nothing yet, go for next time...
	if (mode == GF_ISOM_SEARCH_SYNC_FORWARD) {
		if (next) *sampleNumber = next;
	} else {
		if (prev) *sampleNumber = prev;
	}

	return GF_OK;
}


unsigned int __sk_run_filter(void *ctx, const struct sock_filter_int *insn)
{
	u64 stack[MAX_BPF_STACK / sizeof(u64)];
	u64 regs[MAX_BPF_REG], tmp;
	void *ptr;
	int off;

#define K  insn->imm
#define A  regs[insn->a_reg]
#define X  regs[insn->x_reg]
#define R0 regs[0]

#define CONT	 ({insn++; goto select_insn; })
#define CONT_JMP ({insn++; goto select_insn; })

	static const void *jumptable[256] = {
		[0 ... 255] = &&default_label,
		/* Now overwrite non-defaults ... */
#define DL(A, B, C)	[A|B|C] = &&A##_##B##_##C
		DL(BPF_ALU, BPF_ADD, BPF_X),
		DL(BPF_ALU, BPF_ADD, BPF_K),
		DL(BPF_ALU, BPF_SUB, BPF_X),
		DL(BPF_ALU, BPF_SUB, BPF_K),
		DL(BPF_ALU, BPF_AND, BPF_X),
		DL(BPF_ALU, BPF_AND, BPF_K),
		DL(BPF_ALU, BPF_OR, BPF_X),
		DL(BPF_ALU, BPF_OR, BPF_K),
		DL(BPF_ALU, BPF_LSH, BPF_X),
		DL(BPF_ALU, BPF_LSH, BPF_K),
		DL(BPF_ALU, BPF_RSH, BPF_X),
		DL(BPF_ALU, BPF_RSH, BPF_K),
		DL(BPF_ALU, BPF_XOR, BPF_X),
		DL(BPF_ALU, BPF_XOR, BPF_K),
		DL(BPF_ALU, BPF_MUL, BPF_X),
		DL(BPF_ALU, BPF_MUL, BPF_K),
		DL(BPF_ALU, BPF_MOV, BPF_X),
		DL(BPF_ALU, BPF_MOV, BPF_K),
		DL(BPF_ALU, BPF_DIV, BPF_X),
		DL(BPF_ALU, BPF_DIV, BPF_K),
		DL(BPF_ALU, BPF_MOD, BPF_X),
		DL(BPF_ALU, BPF_MOD, BPF_K),
		DL(BPF_ALU, BPF_NEG, 0),
		DL(BPF_ALU, BPF_END, BPF_TO_BE),
		DL(BPF_ALU, BPF_END, BPF_TO_LE),
		DL(BPF_ALU64, BPF_ADD, BPF_X),
		DL(BPF_ALU64, BPF_ADD, BPF_K),
		DL(BPF_ALU64, BPF_SUB, BPF_X),
		DL(BPF_ALU64, BPF_SUB, BPF_K),
		DL(BPF_ALU64, BPF_AND, BPF_X),
		DL(BPF_ALU64, BPF_AND, BPF_K),
		DL(BPF_ALU64, BPF_OR, BPF_X),
		DL(BPF_ALU64, BPF_OR, BPF_K),
		DL(BPF_ALU64, BPF_LSH, BPF_X),
		DL(BPF_ALU64, BPF_LSH, BPF_K),
		DL(BPF_ALU64, BPF_RSH, BPF_X),
		DL(BPF_ALU64, BPF_RSH, BPF_K),
		DL(BPF_ALU64, BPF_XOR, BPF_X),
		DL(BPF_ALU64, BPF_XOR, BPF_K),
		DL(BPF_ALU64, BPF_MUL, BPF_X),
		DL(BPF_ALU64, BPF_MUL, BPF_K),
		DL(BPF_ALU64, BPF_MOV, BPF_X),
		DL(BPF_ALU64, BPF_MOV, BPF_K),
		DL(BPF_ALU64, BPF_ARSH, BPF_X),
		DL(BPF_ALU64, BPF_ARSH, BPF_K),
		DL(BPF_ALU64, BPF_DIV, BPF_X),
		DL(BPF_ALU64, BPF_DIV, BPF_K),
		DL(BPF_ALU64, BPF_MOD, BPF_X),
		DL(BPF_ALU64, BPF_MOD, BPF_K),
		DL(BPF_ALU64, BPF_NEG, 0),
		DL(BPF_JMP, BPF_CALL, 0),
		DL(BPF_JMP, BPF_JA, 0),
		DL(BPF_JMP, BPF_JEQ, BPF_X),
		DL(BPF_JMP, BPF_JEQ, BPF_K),
		DL(BPF_JMP, BPF_JNE, BPF_X),
		DL(BPF_JMP, BPF_JNE, BPF_K),
		DL(BPF_JMP, BPF_JGT, BPF_X),
		DL(BPF_JMP, BPF_JGT, BPF_K),
		DL(BPF_JMP, BPF_JGE, BPF_X),
		DL(BPF_JMP, BPF_JGE, BPF_K),
		DL(BPF_JMP, BPF_JSGT, BPF_X),
		DL(BPF_JMP, BPF_JSGT, BPF_K),
		DL(BPF_JMP, BPF_JSGE, BPF_X),
		DL(BPF_JMP, BPF_JSGE, BPF_K),
		DL(BPF_JMP, BPF_JSET, BPF_X),
		DL(BPF_JMP, BPF_JSET, BPF_K),
		DL(BPF_JMP, BPF_EXIT, 0),
		DL(BPF_STX, BPF_MEM, BPF_B),
		DL(BPF_STX, BPF_MEM, BPF_H),
		DL(BPF_STX, BPF_MEM, BPF_W),
		DL(BPF_STX, BPF_MEM, BPF_DW),
		DL(BPF_STX, BPF_XADD, BPF_W),
		DL(BPF_STX, BPF_XADD, BPF_DW),
		DL(BPF_ST, BPF_MEM, BPF_B),
		DL(BPF_ST, BPF_MEM, BPF_H),
		DL(BPF_ST, BPF_MEM, BPF_W),
		DL(BPF_ST, BPF_MEM, BPF_DW),
		DL(BPF_LDX, BPF_MEM, BPF_B),
		DL(BPF_LDX, BPF_MEM, BPF_H),
		DL(BPF_LDX, BPF_MEM, BPF_W),
		DL(BPF_LDX, BPF_MEM, BPF_DW),
		DL(BPF_LD, BPF_ABS, BPF_W),
		DL(BPF_LD, BPF_ABS, BPF_H),
		DL(BPF_LD, BPF_ABS, BPF_B),
		DL(BPF_LD, BPF_IND, BPF_W),
		DL(BPF_LD, BPF_IND, BPF_H),
		DL(BPF_LD, BPF_IND, BPF_B),
#undef DL
	};

	regs[FP_REG]  = (u64) (unsigned long) &stack[ARRAY_SIZE(stack)];
	regs[ARG1_REG] = (u64) (unsigned long) ctx;

select_insn:
	goto *jumptable[insn->code];

	/* ALU */
#define ALU(OPCODE, OP)			\
	BPF_ALU64_##OPCODE##_BPF_X:	\
		A = A OP X;		\
		CONT;			\
	BPF_ALU_##OPCODE##_BPF_X:	\
		A = (u32) A OP (u32) X;	\
		CONT;			\
	BPF_ALU64_##OPCODE##_BPF_K:	\
		A = A OP K;		\
		CONT;			\
	BPF_ALU_##OPCODE##_BPF_K:	\
		A = (u32) A OP (u32) K;	\
		CONT;

	ALU(BPF_ADD,  +)
	ALU(BPF_SUB,  -)
	ALU(BPF_AND,  &)
	ALU(BPF_OR,   |)
	ALU(BPF_LSH, <<)
	ALU(BPF_RSH, >>)
	ALU(BPF_XOR,  ^)
	ALU(BPF_MUL,  *)
#undef ALU
	BPF_ALU_BPF_NEG_0:
		A = (u32) -A;
		CONT;
	BPF_ALU64_BPF_NEG_0:
		A = -A;
		CONT;
	BPF_ALU_BPF_MOV_BPF_X:
		A = (u32) X;
		CONT;
	BPF_ALU_BPF_MOV_BPF_K:
		A = (u32) K;
		CONT;
	BPF_ALU64_BPF_MOV_BPF_X:
		A = X;
		CONT;
	BPF_ALU64_BPF_MOV_BPF_K:
		A = K;
		CONT;
	BPF_ALU64_BPF_ARSH_BPF_X:
		(*(s64 *) &A) >>= X;
		CONT;
	BPF_ALU64_BPF_ARSH_BPF_K:
		(*(s64 *) &A) >>= K;
		CONT;
	BPF_ALU64_BPF_MOD_BPF_X:
		if (unlikely(X == 0))
			return 0;
		tmp = A;
		A = do_div(tmp, X);
		CONT;
	BPF_ALU_BPF_MOD_BPF_X:
		if (unlikely(X == 0))
			return 0;
		tmp = (u32) A;
		A = do_div(tmp, (u32) X);
		CONT;
	BPF_ALU64_BPF_MOD_BPF_K:
		tmp = A;
		A = do_div(tmp, K);
		CONT;
	BPF_ALU_BPF_MOD_BPF_K:
		tmp = (u32) A;
		A = do_div(tmp, (u32) K);
		CONT;
	BPF_ALU64_BPF_DIV_BPF_X:
		if (unlikely(X == 0))
			return 0;
		do_div(A, X);
		CONT;
	BPF_ALU_BPF_DIV_BPF_X:
		if (unlikely(X == 0))
			return 0;
		tmp = (u32) A;
		do_div(tmp, (u32) X);
		A = (u32) tmp;
		CONT;
	BPF_ALU64_BPF_DIV_BPF_K:
		do_div(A, K);
		CONT;
	BPF_ALU_BPF_DIV_BPF_K:
		tmp = (u32) A;
		do_div(tmp, (u32) K);
		A = (u32) tmp;
		CONT;
	BPF_ALU_BPF_END_BPF_TO_BE:
		switch (K) {
		case 16:
			A = (__force u16) cpu_to_be16(A);
			break;
		case 32:
			A = (__force u32) cpu_to_be32(A);
			break;
		case 64:
			A = (__force u64) cpu_to_be64(A);
			break;
		}
		CONT;
	BPF_ALU_BPF_END_BPF_TO_LE:
		switch (K) {
		case 16:
			A = (__force u16) cpu_to_le16(A);
			break;
		case 32:
			A = (__force u32) cpu_to_le32(A);
			break;
		case 64:
			A = (__force u64) cpu_to_le64(A);
			break;
		}
		CONT;

	/* CALL */
	BPF_JMP_BPF_CALL_0:
		/* Function call scratches R1-R5 registers, preserves R6-R9,
		 * and stores return value into R0.
		 */
		R0 = (__bpf_call_base + insn->imm)(regs[1], regs[2], regs[3],
						   regs[4], regs[5]);
		CONT;

	/* JMP */
	BPF_JMP_BPF_JA_0:
		insn += insn->off;
		CONT;
	BPF_JMP_BPF_JEQ_BPF_X:
		if (A == X) {
			insn += insn->off;
			CONT_JMP;
		}
		CONT;
	BPF_JMP_BPF_JEQ_BPF_K:
		if (A == K) {
			insn += insn->off;
			CONT_JMP;
		}
		CONT;
	BPF_JMP_BPF_JNE_BPF_X:
		if (A != X) {
			insn += insn->off;
			CONT_JMP;
		}
		CONT;
	BPF_JMP_BPF_JNE_BPF_K:
		if (A != K) {
			insn += insn->off;
			CONT_JMP;
		}
		CONT;
	BPF_JMP_BPF_JGT_BPF_X:
		if (A > X) {
			insn += insn->off;
			CONT_JMP;
		}
		CONT;
	BPF_JMP_BPF_JGT_BPF_K:
		if (A > K) {
			insn += insn->off;
			CONT_JMP;
		}
		CONT;
	BPF_JMP_BPF_JGE_BPF_X:
		if (A >= X) {
			insn += insn->off;
			CONT_JMP;
		}
		CONT;
	BPF_JMP_BPF_JGE_BPF_K:
		if (A >= K) {
			insn += insn->off;
			CONT_JMP;
		}
		CONT;
	BPF_JMP_BPF_JSGT_BPF_X:
		if (((s64)A) > ((s64)X)) {
			insn += insn->off;
			CONT_JMP;
		}
		CONT;
	BPF_JMP_BPF_JSGT_BPF_K:
		if (((s64)A) > ((s64)K)) {
			insn += insn->off;
			CONT_JMP;
		}
		CONT;
	BPF_JMP_BPF_JSGE_BPF_X:
		if (((s64)A) >= ((s64)X)) {
			insn += insn->off;
			CONT_JMP;
		}
		CONT;
	BPF_JMP_BPF_JSGE_BPF_K:
		if (((s64)A) >= ((s64)K)) {
			insn += insn->off;
			CONT_JMP;
		}
		CONT;
	BPF_JMP_BPF_JSET_BPF_X:
		if (A & X) {
			insn += insn->off;
			CONT_JMP;
		}
		CONT;
	BPF_JMP_BPF_JSET_BPF_K:
		if (A & K) {
			insn += insn->off;
			CONT_JMP;
		}
		CONT;
	BPF_JMP_BPF_EXIT_0:
		return R0;

	/* STX and ST and LDX*/
#define LDST(SIZEOP, SIZE)					\
	BPF_STX_BPF_MEM_##SIZEOP:				\
		*(SIZE *)(unsigned long) (A + insn->off) = X;	\
		CONT;						\
	BPF_ST_BPF_MEM_##SIZEOP:				\
		*(SIZE *)(unsigned long) (A + insn->off) = K;	\
		CONT;						\
	BPF_LDX_BPF_MEM_##SIZEOP:				\
		A = *(SIZE *)(unsigned long) (X + insn->off);	\
		CONT;

	LDST(BPF_B,   u8)
	LDST(BPF_H,  u16)
	LDST(BPF_W,  u32)
	LDST(BPF_DW, u64)
#undef LDST
	BPF_STX_BPF_XADD_BPF_W: /* lock xadd *(u32 *)(A + insn->off) += X */
		atomic_add((u32) X, (atomic_t *)(unsigned long)
			   (A + insn->off));
		CONT;
	BPF_STX_BPF_XADD_BPF_DW: /* lock xadd *(u64 *)(A + insn->off) += X */
		atomic64_add((u64) X, (atomic64_t *)(unsigned long)
			     (A + insn->off));
		CONT;
	BPF_LD_BPF_ABS_BPF_W: /* R0 = ntohl(*(u32 *) (skb->data + K)) */
		off = K;
load_word:
		/* BPF_LD + BPD_ABS and BPF_LD + BPF_IND insns are only
		 * appearing in the programs where ctx == skb. All programs
		 * keep 'ctx' in regs[CTX_REG] == R6, sk_convert_filter()
		 * saves it in R6, internal BPF verifier will check that
		 * R6 == ctx.
		 *
		 * BPF_ABS and BPF_IND are wrappers of function calls, so
		 * they scratch R1-R5 registers, preserve R6-R9, and store
		 * return value into R0.
		 *
		 * Implicit input:
		 *   ctx
		 *
		 * Explicit input:
		 *   X == any register
		 *   K == 32-bit immediate
		 *
		 * Output:
		 *   R0 - 8/16/32-bit skb data converted to cpu endianness
		 */
		ptr = load_pointer((struct sk_buff *) ctx, off, 4, &tmp);
		if (likely(ptr != NULL)) {
			R0 = get_unaligned_be32(ptr);
			CONT;
		}
		return 0;
	BPF_LD_BPF_ABS_BPF_H: /* R0 = ntohs(*(u16 *) (skb->data + K)) */
		off = K;
load_half:
		ptr = load_pointer((struct sk_buff *) ctx, off, 2, &tmp);
		if (likely(ptr != NULL)) {
			R0 = get_unaligned_be16(ptr);
			CONT;
		}
		return 0;
	BPF_LD_BPF_ABS_BPF_B: /* R0 = *(u8 *) (ctx + K) */
		off = K;
load_byte:
		ptr = load_pointer((struct sk_buff *) ctx, off, 1, &tmp);
		if (likely(ptr != NULL)) {
			R0 = *(u8 *)ptr;
			CONT;
		}
		return 0;
	BPF_LD_BPF_IND_BPF_W: /* R0 = ntohl(*(u32 *) (skb->data + X + K)) */
		off = K + X;
		goto load_word;
	BPF_LD_BPF_IND_BPF_H: /* R0 = ntohs(*(u16 *) (skb->data + X + K)) */
		off = K + X;
		goto load_half;
	BPF_LD_BPF_IND_BPF_B: /* R0 = *(u8 *) (skb->data + X + K) */
		off = K + X;
		goto load_byte;

	default_label:
		/* If we ever reach this, we have a bug somewhere. */
		WARN_RATELIMIT(1, "unknown opcode %02x\n", insn->code);
		return 0;
#undef CONT_JMP
#undef CONT

#undef R0
#undef X
#undef A
#undef K
}


int sk_detach_filter(struct sock *sk)
{
	int ret = -ENOENT;
	struct sk_filter *filter;

	if (sock_flag(sk, SOCK_FILTER_LOCKED))
		return -EPERM;

	filter = rcu_dereference_protected(sk->sk_filter,
					   sock_owned_by_user(sk));
	if (filter) {
		RCU_INIT_POINTER(sk->sk_filter, NULL);
		sk_filter_uncharge(sk, filter);
		ret = 0;
	}

	return ret;
}


void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
{
	static const u16 decodes[] = {
		[BPF_S_ALU_ADD_K]	= BPF_ALU|BPF_ADD|BPF_K,
		[BPF_S_ALU_ADD_X]	= BPF_ALU|BPF_ADD|BPF_X,
		[BPF_S_ALU_SUB_K]	= BPF_ALU|BPF_SUB|BPF_K,
		[BPF_S_ALU_SUB_X]	= BPF_ALU|BPF_SUB|BPF_X,
		[BPF_S_ALU_MUL_K]	= BPF_ALU|BPF_MUL|BPF_K,
		[BPF_S_ALU_MUL_X]	= BPF_ALU|BPF_MUL|BPF_X,
		[BPF_S_ALU_DIV_X]	= BPF_ALU|BPF_DIV|BPF_X,
		[BPF_S_ALU_MOD_K]	= BPF_ALU|BPF_MOD|BPF_K,
		[BPF_S_ALU_MOD_X]	= BPF_ALU|BPF_MOD|BPF_X,
		[BPF_S_ALU_AND_K]	= BPF_ALU|BPF_AND|BPF_K,
		[BPF_S_ALU_AND_X]	= BPF_ALU|BPF_AND|BPF_X,
		[BPF_S_ALU_OR_K]	= BPF_ALU|BPF_OR|BPF_K,
		[BPF_S_ALU_OR_X]	= BPF_ALU|BPF_OR|BPF_X,
		[BPF_S_ALU_XOR_K]	= BPF_ALU|BPF_XOR|BPF_K,
		[BPF_S_ALU_XOR_X]	= BPF_ALU|BPF_XOR|BPF_X,
		[BPF_S_ALU_LSH_K]	= BPF_ALU|BPF_LSH|BPF_K,
		[BPF_S_ALU_LSH_X]	= BPF_ALU|BPF_LSH|BPF_X,
		[BPF_S_ALU_RSH_K]	= BPF_ALU|BPF_RSH|BPF_K,
		[BPF_S_ALU_RSH_X]	= BPF_ALU|BPF_RSH|BPF_X,
		[BPF_S_ALU_NEG]		= BPF_ALU|BPF_NEG,
		[BPF_S_LD_W_ABS]	= BPF_LD|BPF_W|BPF_ABS,
		[BPF_S_LD_H_ABS]	= BPF_LD|BPF_H|BPF_ABS,
		[BPF_S_LD_B_ABS]	= BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_PROTOCOL]	= BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_PKTTYPE]	= BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_IFINDEX]	= BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_NLATTR]	= BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_NLATTR_NEST]	= BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_MARK]	= BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_QUEUE]	= BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_HATYPE]	= BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_RXHASH]	= BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_CPU]		= BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_ALU_XOR_X]	= BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_SECCOMP_LD_W] = BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_VLAN_TAG]	= BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_VLAN_TAG_PRESENT] = BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_ANC_PAY_OFFSET]	= BPF_LD|BPF_B|BPF_ABS,
		[BPF_S_LD_W_LEN]	= BPF_LD|BPF_W|BPF_LEN,
		[BPF_S_LD_W_IND]	= BPF_LD|BPF_W|BPF_IND,
		[BPF_S_LD_H_IND]	= BPF_LD|BPF_H|BPF_IND,
		[BPF_S_LD_B_IND]	= BPF_LD|BPF_B|BPF_IND,
		[BPF_S_LD_IMM]		= BPF_LD|BPF_IMM,
		[BPF_S_LDX_W_LEN]	= BPF_LDX|BPF_W|BPF_LEN,
		[BPF_S_LDX_B_MSH]	= BPF_LDX|BPF_B|BPF_MSH,
		[BPF_S_LDX_IMM]		= BPF_LDX|BPF_IMM,
		[BPF_S_MISC_TAX]	= BPF_MISC|BPF_TAX,
		[BPF_S_MISC_TXA]	= BPF_MISC|BPF_TXA,
		[BPF_S_RET_K]		= BPF_RET|BPF_K,
		[BPF_S_RET_A]		= BPF_RET|BPF_A,
		[BPF_S_ALU_DIV_K]	= BPF_ALU|BPF_DIV|BPF_K,
		[BPF_S_LD_MEM]		= BPF_LD|BPF_MEM,
		[BPF_S_LDX_MEM]		= BPF_LDX|BPF_MEM,
		[BPF_S_ST]		= BPF_ST,
		[BPF_S_STX]		= BPF_STX,
		[BPF_S_JMP_JA]		= BPF_JMP|BPF_JA,
		[BPF_S_JMP_JEQ_K]	= BPF_JMP|BPF_JEQ|BPF_K,
		[BPF_S_JMP_JEQ_X]	= BPF_JMP|BPF_JEQ|BPF_X,
		[BPF_S_JMP_JGE_K]	= BPF_JMP|BPF_JGE|BPF_K,
		[BPF_S_JMP_JGE_X]	= BPF_JMP|BPF_JGE|BPF_X,
		[BPF_S_JMP_JGT_K]	= BPF_JMP|BPF_JGT|BPF_K,
		[BPF_S_JMP_JGT_X]	= BPF_JMP|BPF_JGT|BPF_X,
		[BPF_S_JMP_JSET_K]	= BPF_JMP|BPF_JSET|BPF_K,
		[BPF_S_JMP_JSET_X]	= BPF_JMP|BPF_JSET|BPF_X,
	};
	u16 code;

	code = filt->code;

	to->code = decodes[code];
	to->jt = filt->jt;
	to->jf = filt->jf;
	to->k = filt->k;
}


  void operator()(const CPUDevice& d, typename TTypes<T, 4>::ConstTensor input,
                  typename TTypes<T, 3>::ConstTensor filter,
                  typename TTypes<T, 4>::ConstTensor out_backprop,
                  int stride_rows, int stride_cols, int rate_rows,
                  int rate_cols, int pad_top, int pad_left,
                  typename TTypes<T, 3>::Tensor filter_backprop) {
    const int batch = input.dimension(0);
    const int input_rows = input.dimension(1);
    const int input_cols = input.dimension(2);
    const int depth = input.dimension(3);

    const int filter_rows = filter.dimension(0);
    const int filter_cols = filter.dimension(1);

    const int output_rows = out_backprop.dimension(1);
    const int output_cols = out_backprop.dimension(2);

    // Initialize gradient with all zeros.
    filter_backprop.setZero();

    // This is a reference implementation, likely to be slow.
    // TODO(gpapan): Write multi-threaded implementation.
    // In the case of multiple argmax branches, we only back-propagate along the
    // last branch, i.e., the one with largest value of `h * filter_cols + w`,
    // similarly to the max-pooling backward routines.
    for (int b = 0; b < batch; ++b) {
      for (int h_out = 0; h_out < output_rows; ++h_out) {
        int h_beg = h_out * stride_rows - pad_top;
        for (int w_out = 0; w_out < output_cols; ++w_out) {
          int w_beg = w_out * stride_cols - pad_left;
          for (int d = 0; d < depth; ++d) {
            T cur_val = Eigen::NumTraits<T>::lowest();
            int h_max = 0;
            int w_max = 0;
            for (int h = 0; h < filter_rows; ++h) {
              const int h_in = h_beg + h * rate_rows;
              if (h_in >= 0 && h_in < input_rows) {
                for (int w = 0; w < filter_cols; ++w) {
                  const int w_in = w_beg + w * rate_cols;
                  if (w_in >= 0 && w_in < input_cols) {
                    const T val = input(b, h_in, w_in, d) + filter(h, w, d);
                    if (val > cur_val) {
                      cur_val = val;
                      h_max = h;
                      w_max = w;
                    }
                  }
                }
              }
            }
            if (h_max < filter_rows && w_max < filter_cols) {
              filter_backprop(h_max, w_max, d) +=
                  out_backprop(b, h_out, w_out, d);
            }
          }
        }
      }
    }
  }


  void Compute(OpKernelContext* context) override {
    const Tensor& input = context->input(0);
    const Tensor& filter = context->input(1);
    const Tensor& out_backprop = context->input(2);

    // Determine relevant sizes from input and filters.
    int stride_rows = 0, stride_cols = 0;
    int rate_rows = 0, rate_cols = 0;
    int64 pad_top = 0, pad_left = 0;
    int64 out_rows = 0, out_cols = 0;
    ParseSizes(context, strides_, rates_, padding_, &stride_rows, &stride_cols,
               &rate_rows, &rate_cols, &pad_top, &pad_left, &out_rows,
               &out_cols);
    if (!context->status().ok()) return;

    // Verify that the incoming gradient tensor has the expected size
    // [ batch, out_rows, out_cols, depth ]
    const int batch = input.dim_size(0);
    const int depth = input.dim_size(3);
    OP_REQUIRES(context,
                batch == out_backprop.dim_size(0) &&
                    out_rows == out_backprop.dim_size(1) &&
                    out_cols == out_backprop.dim_size(2) &&
                    depth == out_backprop.dim_size(3),
                errors::InvalidArgument("out_backprop has incompatible size."));

    // The computed filter_backprop has the same dimensions as the filter:
    // [ batch, input_rows, input_cols, depth ]
    Tensor* filter_backprop = nullptr;
    OP_REQUIRES_OK(
        context, context->allocate_output(0, filter.shape(), &filter_backprop));

    // If there is nothing to compute, return.
    if (filter.shape().num_elements() == 0) {
      return;
    }

    functor::DilationBackpropFilter<Device, T>()(
        context->eigen_device<Device>(), input.tensor<T, 4>(),
        filter.tensor<T, 3>(), out_backprop.tensor<T, 4>(), stride_rows,
        stride_cols, rate_rows, rate_cols, pad_top, pad_left,
        filter_backprop->tensor<T, 3>());
  }


  explicit DilationBackpropFilterOp(OpKernelConstruction* context)
      : OpKernel(context) {
    ParseAttributes(context, &strides_, &rates_, &padding_);
  }


static MagickBooleanType DitherImage(Image *image,CubeInfo *cube_info,
  ExceptionInfo *exception)
{
  CacheView
    *image_view;

  MagickBooleanType
    status;

  register ssize_t
    i;

  size_t
    depth;

  if (cube_info->quantize_info->dither_method != RiemersmaDitherMethod)
    return(FloydSteinbergDither(image,cube_info,exception));
  /*
    Distribute quantization error along a Hilbert curve.
  */
  (void) ResetMagickMemory(cube_info->error,0,ErrorQueueLength*
    sizeof(*cube_info->error));
  cube_info->x=0;
  cube_info->y=0;
  i=MagickMax((ssize_t) image->columns,(ssize_t) image->rows);
  for (depth=1; i != 0; depth++)
    i>>=1;
  if ((ssize_t) (1L << depth) < MagickMax((ssize_t) image->columns,(ssize_t) image->rows))
    depth++;
  cube_info->offset=0;
  cube_info->span=(MagickSizeType) image->columns*image->rows;
  image_view=AcquireAuthenticCacheView(image,exception);
  if (depth > 1)
    Riemersma(image,image_view,cube_info,depth-1,NorthGravity,exception);
  status=RiemersmaDither(image,image_view,cube_info,ForgetGravity,exception);
  image_view=DestroyCacheView(image_view);
  return(status);
}


static int oprep(RAsm *a, ut8 *data, const Opcode *op) {
	int l = 0;
	LookupTable *lt_ptr;
	int retval;
	if (!strcmp (op->mnemonic, "rep") ||
	    !strcmp (op->mnemonic, "repe") ||
	    !strcmp (op->mnemonic, "repz")) {
		data[l++] = 0xf3;
	} else if (!strcmp (op->mnemonic, "repne") ||
	           !strcmp (op->mnemonic, "repnz")) {
		data[l++] = 0xf2;
	}
	Opcode instr = {0};
	parseOpcode (a, op->operands[0].rep_op, &instr);

	for (lt_ptr = oplookup; strcmp (lt_ptr->mnemonic, "null"); lt_ptr++) {
		if (!r_str_casecmp (instr.mnemonic, lt_ptr->mnemonic)) {
			if (lt_ptr->opcode > 0) {
				if (lt_ptr->only_x32 && a->bits == 64) {
					return -1;
				}
				ut8 *ptr = (ut8 *)&lt_ptr->opcode;
				int i = 0;
				for (; i < lt_ptr->size; i++) {
					data[i + l] = ptr[lt_ptr->size - (i + 1)];
				}
				free (instr.mnemonic);
				return l + lt_ptr->size;
			} else {
				if (lt_ptr->opdo) {
					data += l;
					if (instr.has_bnd) {
						data[l] = 0xf2;
						data++;
					}
					retval = lt_ptr->opdo (a, data, &instr);
					// if op supports bnd then the first byte will
					// be 0xf2.
					if (instr.has_bnd) {
						retval++;
					}
					return l + retval;
				}
				break;
			}
		}
	}
	free (instr.mnemonic);
	return -1;
}


GF_Err gf_seng_get_stream_config(GF_SceneEngine *seng, u32 idx, u16 *ESID, const u8 **config, u32 *config_len, u32 *streamType, u32 *codec_id, u32 *timeScale)
{
	GF_StreamContext *sc = gf_list_get(seng->ctx->streams, idx);
	if (!sc || !ESID || !config || !config_len) return GF_BAD_PARAM;
	*ESID = sc->ESID;
	*config = sc->dec_cfg;
	*config_len = sc->dec_cfg_len;
	if (streamType) *streamType = sc->streamType;
	if (codec_id) *codec_id = sc->codec_id;
	if (timeScale) *timeScale = sc->timeScale;
	return GF_OK;
}


GF_Err stss_box_dump(GF_Box *a, FILE * trace)
{
	GF_SyncSampleBox *p;
	u32 i;

	if (dump_skip_samples)
		return GF_OK;

	p = (GF_SyncSampleBox *)a;
	gf_isom_box_dump_start(a, "SyncSampleBox", trace);
	gf_fprintf(trace, "EntryCount=\"%d\">\n", p->nb_entries);

	if (!p->sampleNumbers && p->size) {
		gf_fprintf(trace, "<!--Warning: No Key Frames indications-->\n");
	} else if (p->sampleNumbers) {
		for (i=0; i<p->nb_entries; i++) {
			gf_fprintf(trace, "<SyncSampleEntry sampleNumber=\"%u\"/>\n", p->sampleNumbers[i]);
		}
	}
	if (!p->size) {
			gf_fprintf(trace, "<SyncSampleEntry sampleNumber=\"\"/>\n");
	}
	gf_isom_box_dump_done("SyncSampleBox", a, trace);
	return GF_OK;
}


static Bool ttml_same_attr(GF_XMLNode *n1, GF_XMLNode *n2)
{
	u32 i=0;
	GF_XMLAttribute *att1;
	while ( (att1 = gf_list_enum(n1->attributes, &i))) {
		Bool found = GF_FALSE;
		u32 j=0;
		GF_XMLAttribute *att2;
		while ( (att2 = gf_list_enum(n2->attributes, &j))) {
			if (!strcmp(att1->name, att2->name) && !strcmp(att1->value, att2->value)) {
				found = GF_TRUE;
				break;
			}
		}
		if (!found) return GF_FALSE;
	}
	return GF_TRUE;
}


}
static JSValue js_sys_file_move(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
	return js_sys_file_opt(ctx, this_val, argc, argv, OPT_FILEMOVE);


GF_Err mdat_box_dump(GF_Box *a, FILE * trace)
{
	GF_MediaDataBox *p;
	const char *name = (a->type==GF_ISOM_BOX_TYPE_IDAT ? "ItemDataBox" : "MediaDataBox");
	p = (GF_MediaDataBox *)a;
	gf_isom_box_dump_start(a, name, trace);
	gf_fprintf(trace, "dataSize=\""LLD"\">\n", p->dataSize);
	gf_isom_box_dump_done(name, a, trace);
	return GF_OK;
}


static JSValue js_file_prop_get(JSContext *ctx, JSValueConst this_val, int magic)
{
	FILE *f = JS_GetOpaque(this_val, file_class_id);
	if (!f) return GF_JS_EXCEPTION(ctx);

	switch (magic) {
	case JS_FILE_POS:
		return JS_NewInt64(ctx, gf_ftell(f));
	case JS_FILE_EOF:
		return JS_NewBool(ctx, gf_feof(f));
	case JS_FILE_ERROR:
		return JS_NewInt32(ctx, gf_ferror(f) );
	case JS_FILE_SIZE:
		return JS_NewInt64(ctx, gf_fsize(f) );
	case JS_FILE_IS_GFIO:
		return JS_NewBool(ctx, gf_fileio_check(f));
	}
	return JS_UNDEFINED;


GF_Err traf_box_dump(GF_Box *a, FILE * trace)
{
	gf_isom_box_dump_start(a, "TrackFragmentBox", trace);
	gf_fprintf(trace, ">\n");
	gf_isom_box_dump_done("TrackFragmentBox", a, trace);
	return GF_OK;
}


static JSValue amix_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv)
{
	u32 a_fmt=0;
	u32 channels, samples_gap, fade_len;
	AMixCtx *mix;
	JSValue anobj;

	if (argc != 4) return js_throw_err(ctx, GF_BAD_PARAM);

	const char *fmt = JS_ToCString(ctx, argv[0]);
	if (!fmt) return GF_JS_EXCEPTION(ctx);
	//we only support these formats for the time being, all in packed mode
	if (!strcmp(fmt, "s16")) a_fmt = 1;
	else if (!strcmp(fmt, "s32")) a_fmt = 2;
	else if (!strcmp(fmt, "flt")) a_fmt = 3;
	else if (!strcmp(fmt, "dbl")) a_fmt = 4;
	JS_FreeCString(ctx, fmt);
	if (!a_fmt) return GF_JS_EXCEPTION(ctx);

	if (JS_ToInt32(ctx, &channels, argv[1])) return GF_JS_EXCEPTION(ctx);
	if (JS_ToInt32(ctx, &samples_gap, argv[2])) return GF_JS_EXCEPTION(ctx);
	if (JS_ToInt32(ctx, &fade_len, argv[3])) return GF_JS_EXCEPTION(ctx);
	if (!channels) return js_throw_err(ctx, GF_BAD_PARAM);

	GF_SAFEALLOC(mix, AMixCtx);
	mix->channels = channels;
	mix->samples_gap = samples_gap;
	mix->fade_len = fade_len;
	mix->chan_buf = gf_malloc(sizeof(Double) * channels);
	if (!mix->chan_buf) {
		gf_free(mix);
		return js_throw_err(ctx, GF_OUT_OF_MEM);
	}

	switch (a_fmt) {
	case 1:
		mix->sample_size = 2;
		mix->get_sample = amix_get_s16;
		mix->set_sample = amix_set_s16;
		break;
	case 2:
		mix->sample_size = 4;
		mix->get_sample = amix_get_s32;
		mix->set_sample = amix_set_s32;
		break;
	case 3:
		mix->sample_size = 4;
		mix->get_sample = amix_get_flt;
		mix->set_sample = amix_set_flt;
		break;
	case 4:
		mix->sample_size = 8;
		mix->get_sample = amix_get_dbl;
		mix->set_sample = amix_set_dbl;
		break;
	}

	anobj = JS_NewObjectClass(ctx, amix_class_id);
	if (JS_IsException(anobj)) {
		gf_free(mix);
		return anobj;
	}
	JS_SetOpaque(anobj, mix);
	return anobj;


static JSValue js_audio_mix(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
	u32 nb_samples, i, j, k, nb_src, fade_length=0;
	u64 audio_time;
	JSValue v;
	s32 res;
	size_t ab_size;
	u8 *mix_ab;
	u32 max_chan = 0;
	PidMix *pids;
	AMixCtx *mix = JS_GetOpaque(this_val, amix_class_id);
	if (!mix) return GF_JS_EXCEPTION(ctx);

	if (argc != 3) return GF_JS_EXCEPTION(ctx);

	if (JS_ToInt64(ctx, &audio_time, argv[0])) return GF_JS_EXCEPTION(ctx);
	mix_ab = JS_GetArrayBuffer(ctx, &ab_size, argv[1]);
	if (!mix_ab) return GF_JS_EXCEPTION(ctx);
	nb_samples = (u32) (ab_size / mix->channels / mix->sample_size);

	v = JS_GetPropertyStr(ctx, argv[2], "length");
	if (JS_IsException(v)) return GF_JS_EXCEPTION(ctx);

	if (JS_ToInt32(ctx, &nb_src, v)) {
		JS_FreeValue(ctx, v);
		return GF_JS_EXCEPTION(ctx);
	}
	JS_FreeValue(ctx, v);

	if (mix->nb_inputs < nb_src) {
		mix->inputs = gf_realloc(mix->inputs, sizeof(PidMix) * nb_src);
		if (!mix->inputs) return js_throw_err(ctx, GF_OUT_OF_MEM);
		mix->nb_inputs = nb_src;
	}
	pids = mix->inputs;

	//update current input states
	for (i=0; i<nb_src; i++) {
		PidMix *pid = &pids[i];
		pid->jspid = JS_GetPropertyUint32(ctx, argv[2], i);

		v = JS_GetPropertyStr(ctx, pid->jspid, "last_sample_time");
		res = JS_ToInt64(ctx, &pid->last_sample_time, v);
		JS_FreeValue(ctx, v);
		//assume first sample if not set
		if (res) pid->last_sample_time = 0;

		v = JS_GetPropertyStr(ctx, pid->jspid, "frame_ts");
		res = JS_ToInt64(ctx, &pid->frame_ts, v);
		JS_FreeValue(ctx, v);
		//we must have a frame timestamp in audio timescale
		if (res) return GF_JS_EXCEPTION(ctx);

		v = JS_GetPropertyStr(ctx, pid->jspid, "samples_used");
		res = JS_ToInt32(ctx, &pid->samples_used, v);
		JS_FreeValue(ctx, v);
		//if not set, assume first sample
		if (res) pid->samples_used = 0;

		v = JS_GetPropertyStr(ctx, pid->jspid, "channels");
		res = JS_ToInt32(ctx, &pid->channels, v);
		JS_FreeValue(ctx, v);
		//we must have the number of channels for this source
		if (res || !pid->channels) return GF_JS_EXCEPTION(ctx);

		//we must have the audio data
		v = JS_GetPropertyStr(ctx, pid->jspid, "data");
		pid->data = JS_GetArrayBuffer(ctx, &pid->data_size, v);
		JS_FreeValue(ctx, v);

		v = JS_GetPropertyStr(ctx, pid->jspid, "nb_samples");
		res = JS_ToInt32(ctx, &pid->nb_samples, v);
		JS_FreeValue(ctx, v);
		//if not set, derive from data size
		if (res) {
			pid->nb_samples = (u32) (pid->data_size / pid->channels / mix->sample_size);
		}
		v = JS_GetPropertyStr(ctx, pid->jspid, "fade");
		res = JS_ToInt32(ctx, &pid->fade, v);
		JS_FreeValue(ctx, v);
		if (res) pid->fade = 0;
		if (pid->fade) fade_length++;

		v = JS_GetPropertyStr(ctx, pid->jspid, "volume");
		res = JS_ToFloat64(ctx, &pid->volume, v);
		JS_FreeValue(ctx, v);
		if (res) pid->volume = 1.0;

		if (pid->channels>max_chan)
			max_chan = pid->channels;

		pid->consumed = 0;
	}
	if (max_chan > mix->max_pid_channels) {
		mix->in_chan_buf = gf_realloc(mix->in_chan_buf, sizeof(Double) * max_chan);
		if (!mix->in_chan_buf) return js_throw_err(ctx, GF_OUT_OF_MEM);
		mix->max_pid_channels = max_chan;
	}
	if (fade_length) {
		fade_length = MIN(mix->fade_len, nb_samples);
	}

	for (i=0; i<nb_samples; i++) {
		u32 active=0;
		memset(mix->chan_buf, 0, sizeof(Double) * mix->channels);

		for (j=0; j<nb_src; j++) {
			PidMix *pid = &pids[j];

			//for the time being, as soon as we start writing audio we no longer check sync
			if (!pid->last_sample_time) {
				if (pid->frame_ts + pid->samples_used  > audio_time + i) {
					continue;
				}
				pid->last_sample_time = 1; //pid.frame_ts + pid.sample_used;
				JS_SetPropertyStr(ctx, pid->jspid, "last_sample_time", JS_NewInt64(ctx, pid->last_sample_time) );
			} else {
				//audio discontinuity
				if (pid->frame_ts + pid->samples_used  > audio_time + i + mix->samples_gap) {
					continue;
				}
			}

			u32 s_pos = pid->samples_used + pid->consumed;
			if (s_pos >= pid->nb_samples) {
				assert(0);
				GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[AVMix] error mixing\n"));
			}
			u32 pos = s_pos * pid->channels;
			u8 *buf = pid->data + mix->sample_size * pos;
			for (k=0; k<pid->channels; k++) {
				mix->in_chan_buf[k] = mix->get_sample(buf);
				buf += mix->sample_size;
			}

			active += 1;

			Double fade_scale = 1;
			if (pid->fade) {
				//fade from 0 to 1 starting at pos=0 up to fade_length
				if (pid->fade==1) {
					if (s_pos<fade_length) {
						fade_scale = s_pos/fade_length;
					} else {
						pid->fade = 0;
						JS_SetPropertyStr(ctx, pid->jspid, "fade", JS_NewInt32(ctx, pid->fade) );
					}
				}
				//fade from 1 to 0 starting at pos=nb_samples-fade_length up to nb_samples
				else if (pid->fade==2) {
					if (s_pos>nb_samples-fade_length ) {
						fade_scale = (nb_samples - s_pos)/fade_length;
					}
				}
			}
			fade_scale *= pid->volume;

			//todo , proper down/up mix ...
			for (k=0; k<mix->channels; k++) {
				Double s_val;
				if (pid->channels < k )
					s_val = mix->in_chan_buf[0];
				else
				s_val = mix->in_chan_buf[k];

				mix->chan_buf[k] += s_val * fade_scale;
			}
			pid->consumed ++;
		}

		u8 *dst = mix_ab + mix->sample_size * (i * mix->channels);
		for (j=0; j< mix->channels; j++) {
			Double sval = active ? (mix->chan_buf[j] / active) : 0;
			mix->set_sample(dst, sval);
			dst += mix->sample_size;
		}
	}

	//update pid values
	for (i=0; i<nb_src; i++) {
		PidMix *pid = &pids[i];
		pid->samples_used += pid->consumed;
		JS_SetPropertyStr(ctx, pid->jspid, "samples_used", JS_NewInt32(ctx, pid->samples_used));

		JS_FreeValue(ctx, pid->jspid);
	}
	return JS_UNDEFINED;


GF_Err chnl_box_dump(GF_Box *a, FILE * trace)
{
	GF_ChannelLayoutBox *p = (GF_ChannelLayoutBox *) a;
	gf_isom_box_dump_start(a, "ChannelLayoutBox", trace);
	gf_fprintf(trace, " stream_structure=\"%d\"", p->layout.stream_structure);
	if (p->layout.stream_structure & 2)
		gf_fprintf(trace, " object_count=\"%d\"", p->layout.object_count);

	if (p->layout.stream_structure & 1) {
		gf_fprintf(trace, " definedLayout=\"%d\"", p->layout.definedLayout);
		if (p->layout.definedLayout!=0) {
			gf_fprintf(trace, " omittedChannelsMap=\""LLU"\"", p->layout.omittedChannelsMap);
		}
	}

	gf_fprintf(trace, ">\n");
	if ((p->layout.stream_structure & 1) && (p->layout.definedLayout==0)) {
		u32 i;
		for (i=0; i<p->layout.channels_count; i++) {
			gf_fprintf(trace, "<Speaker position=\"%d\"", p->layout.layouts[i].position);
			if (p->layout.layouts[i].position==126) {
				gf_fprintf(trace, " azimuth=\"%d\" elevation=\"%d\"", p->layout.layouts[i].azimuth, p->layout.layouts[i].elevation);
			}
			gf_fprintf(trace, "/>\n");
		}
	}

	gf_isom_box_dump_done("ChannelLayoutBox", a, trace);
	return GF_OK;
}


GF_Err flxs_box_dump(GF_Box *a, FILE * trace)
{
	if (!a) return GF_BAD_PARAM;
	gf_isom_box_dump_start(a, "AdobeFlashAccessParamsBox", trace);
	gf_fprintf(trace, ">\n");
	gf_isom_box_dump_done("AdobeFlashAccessParamsBox", a, trace);
	return GF_OK;
}


GF_Err def_parent_full_box_dump(GF_Box *a, FILE *trace)
{
	char *name = "GenericFullBox";

	switch (a->type) {
	case GF_ISOM_BOX_TYPE_MVCI:
		name = "MultiviewInformationBox";
		break;
	}

	gf_isom_box_dump_start(a, name, trace);
	gf_fprintf(trace, ">\n");
	gf_isom_box_dump_done(name, a, trace);
	return GF_OK;
}


static void svg_lsr_set_v2(GF_SVG_Parser *parser)
{
	u32 i;
	if (parser->load->ctx && parser->load->ctx->root_od) {
		for (i=0; i<gf_list_count(parser->load->ctx->root_od->ESDescriptors); i++) {
			GF_ESD *esd = (GF_ESD *)gf_list_get(parser->load->ctx->root_od->ESDescriptors, i);
			if (esd->decoderConfig->streamType==GF_STREAM_SCENE) {
				GF_LASERConfig *cfg = (GF_LASERConfig *)esd->decoderConfig->decoderSpecificInfo;
				if (cfg && (cfg->tag==GF_ODF_LASER_CFG_TAG)) {
					if (!cfg->extensionIDBits) cfg->extensionIDBits = 2;
				}
			}
		}
	}
}


GF_Err mvex_box_dump(GF_Box *a, FILE * trace)
{
	gf_isom_box_dump_start(a, "MovieExtendsBox", trace);
	gf_fprintf(trace, ">\n");
	gf_isom_box_dump_done("MovieExtendsBox", a, trace);
	return GF_OK;
}


GF_Err trex_box_dump(GF_Box *a, FILE * trace)
{
	GF_TrackExtendsBox *p;
	p = (GF_TrackExtendsBox *)a;
	gf_isom_box_dump_start(a, "TrackExtendsBox", trace);
	gf_fprintf(trace, "TrackID=\"%d\"", p->trackID);
	gf_fprintf(trace, " SampleDescriptionIndex=\"%d\" SampleDuration=\"%d\" SampleSize=\"%d\"", p->def_sample_desc_index, p->def_sample_duration, p->def_sample_size);
	gf_fprintf(trace, ">\n");
	sample_flags_dump("DefaultSampleFlags", p->def_sample_flags, trace);
	gf_isom_box_dump_done("TrackExtendsBox", a, trace);
	return GF_OK;
}


		gf_free(info);
	}
	gf_list_del(pinfos);

	return nb_periods;
}

static void dasher_init_utc(GF_Filter *filter, GF_DasherCtx *ctx)
{
	const char *cache_name;
	u32 size;
	u8 *data;
	u64 remote_utc;
	GF_Err e;
	GF_DownloadSession *sess;
	GF_DownloadManager *dm;
	char *url;
	DasherUTCTimingType def_type = DASHER_UTCREF_NONE;

	ctx->utc_initialized = GF_TRUE;
	ctx->utc_timing_type = DASHER_UTCREF_NONE;
	if (!ctx->utcs) {
		return;
	}
	url = ctx->utcs;
	if (!strncmp(url, "xsd@", 4)) {
		def_type = DASHER_UTCREF_XSDATE;
		url += 4;
	}

	dm  = gf_filter_get_download_manager(filter);
	if (!dm) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Failed to get download manager, cannot sync to remote UTC clock\n"));
		return;
	}
	if (!strcmp(ctx->utcs, "inband")) {
		ctx->utc_timing_type = DASHER_UTCREF_INBAND;
		return;
	}

	sess = gf_dm_sess_new(dm, url, GF_NETIO_SESSION_MEMORY_CACHE|GF_NETIO_SESSION_NOT_THREADED, NULL, NULL, &e);
	if (e) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Failed to create session for remote UTC source %s: %s - local clock will be used instead\n", url, gf_error_to_string(e) ));
		return;
	}
	while (1) {
		GF_NetIOStatus status;
		e = gf_dm_sess_process(sess);
		if (e) break;
		gf_dm_sess_get_stats(sess, NULL, NULL, NULL, NULL, NULL, &status);
		if (status>=GF_NETIO_DATA_TRANSFERED) break;
	}
	if (e<0) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Failed to fetch remote UTC source %s: %s\n", url, gf_error_to_string(e) ));
		gf_dm_sess_del(sess);
		return;
	}
	cache_name = gf_dm_sess_get_cache_name(sess);
	gf_blob_get(cache_name, &data, &size, NULL);
	if (data) {
		//xsDate or isoDate - we always signal using iso
		if (strchr(data, 'T')) {
			remote_utc = gf_net_parse_date(data);
			if (remote_utc)
				ctx->utc_timing_type = def_type ? def_type : DASHER_UTCREF_ISO;
		}
		//ntp
		else if (sscanf(data, LLU, &remote_utc) == 1) {
			//ntp value not counted since 1900, assume format is seconds till 1 jan 1970
			if (remote_utc<=GF_NTP_SEC_1900_TO_1970) {
				remote_utc = remote_utc*1000;
			} else {
				remote_utc = gf_net_ntp_to_utc(remote_utc);
			}
			if (remote_utc)
				ctx->utc_timing_type = DASHER_UTCREF_NTP;
		}
	}
	gf_blob_release(cache_name);

	//not match, try http date
	if (!ctx->utc_timing_type) {
		const char *hdr = gf_dm_sess_get_header(sess, "Date");
		if (hdr) {
			//http-head
			remote_utc = gf_net_parse_date(hdr);
			if (remote_utc)
				ctx->utc_timing_type = DASHER_UTCREF_HTTP_HEAD;
		}
	}

	if (!ctx->utc_timing_type) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[DASH] Failed to parse response %s from remote UTC source %s\n", data, url ));
	} else {
		ctx->utc_diff = (s32) ( (s64) gf_net_get_utc() - (s64) remote_utc );
		if (ABS(ctx->utc_diff) > 3600000) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] Diff between local clock and remote %s is %d, way too large! Assuming 0 ms UTC diff\n", url, ctx->utc_diff));
			ctx->utc_diff = 0;
		} else {
			GF_LOG(GF_LOG_INFO, GF_LOG_DASH, ("[Dasher] Synchronized clock to remote %s - UTC diff (local - remote) %d ms\n", url, ctx->utc_diff));
		}

		if (!gf_list_count(ctx->mpd->utc_timings) ) {
			Bool dashif_ok = GF_FALSE;
			GF_MPD_Descriptor *utc_t;
			GF_SAFEALLOC(utc_t, GF_MPD_Descriptor);
			utc_t->value = gf_strdup(url);
			switch (ctx->utc_timing_type) {
			case DASHER_UTCREF_HTTP_HEAD:
				utc_t->scheme_id_uri = gf_strdup("urn:mpeg:dash:utc:http-head:2014");
				break;
			case DASHER_UTCREF_XSDATE:
				utc_t->scheme_id_uri = gf_strdup("urn:mpeg:dash:utc:http-xsdate:2014");
				dashif_ok = GF_TRUE;
				break;
			case DASHER_UTCREF_ISO:
				utc_t->scheme_id_uri = gf_strdup("urn:mpeg:dash:utc:http-iso:2014");
				dashif_ok = GF_TRUE;
				break;
			case DASHER_UTCREF_NTP:
				utc_t->scheme_id_uri = gf_strdup("urn:mpeg:dash:utc:http-ntp:2014");
				dashif_ok = GF_TRUE;
				break;
			case DASHER_UTCREF_INBAND:
				utc_t->scheme_id_uri = gf_strdup("urn:mpeg:dash:utc:direct:2014");
				break;
			default:
				break;
			}
			if (!dashif_ok && (ctx->profile==GF_DASH_PROFILE_DASHIF_LL)) {
				GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] UTC reference %s allowed in DASH-IF Low Latency profile\n\tswitching to regular live profile\n", utc_t->scheme_id_uri));
				ctx->profile = GF_DASH_PROFILE_LIVE;
			}


static JSValue js_sys_error_string(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
	GF_Err e;
	if (argc < 1) return GF_JS_EXCEPTION(ctx);
	if (JS_ToInt32(ctx, (int32_t *) &e, argv[0]))
		return GF_JS_EXCEPTION(ctx);
	return JS_NewString(ctx, gf_error_to_string(e) );
}


GF_Err gf_decrypt_fragment(GF_ISOFile *mp4, const char *drm_file, const char *dst_file, const char *fragment_name, u32 fs_dump_flags)
{
	return gf_decrypt_file_ex(mp4, drm_file, dst_file, 0, fragment_name, fs_dump_flags);
}


GF_Err dvvC_box_dump(GF_Box *a, FILE * trace)
{
	return dvcC_box_dump(a, trace);
}


static JSValue file_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv)
{
	JSValue anobj;
	FILE *f=NULL;

	if (!argc) {
		f = gf_file_temp(NULL);
		if (!f) {
			return js_throw_err(ctx, GF_OUT_OF_MEM);
		}
	} else {
		GF_Err e = GF_OK;
		const char *name=NULL, *mode=NULL, *parent_io=NULL;
		name = JS_ToCString(ctx, argv[0] );
		if (argc>1) {
			mode = JS_ToCString(ctx, argv[1] );
			if (argc>2) {
				parent_io = JS_ToCString(ctx, argv[2] );
			}
		}

		if (!name || !mode) {
			e = GF_BAD_PARAM;
		} else {
			f = gf_fopen_ex(name, parent_io, mode, GF_FALSE);
			if (!f) e = GF_URL_ERROR;
		}
		if (name) JS_FreeCString(ctx, name);
		if (mode) JS_FreeCString(ctx, mode);
		if (parent_io) JS_FreeCString(ctx, parent_io);

		if (e) {
			return js_throw_err(ctx, e);
		}
	}

	anobj = JS_NewObjectClass(ctx, file_class_id);
	if (JS_IsException(anobj)) {
		gf_fclose(f);
		return anobj;
	}
	JS_SetOpaque(anobj, f);
	return anobj;


GF_Err adkm_box_dump(GF_Box *a, FILE * trace)
{
	if (!a) return GF_BAD_PARAM;
	gf_isom_box_dump_start(a, "AdobeDRMKeyManagementSystemBox", trace);

	gf_fprintf(trace, ">\n");
	gf_isom_box_dump_done("AdobeDRMKeyManagementSystemBox", a, trace);
	return GF_OK;
}


GF_Err edts_box_dump(GF_Box *a, FILE * trace)
{
	gf_isom_box_dump_start(a, "EditBox", trace);
	gf_fprintf(trace, ">\n");
	gf_isom_box_dump_done("EditBox", a, trace);
	return GF_OK;
}


static GF_ESD *lsr_parse_header(GF_SVG_Parser *parser, const char *name, const char *name_space, const GF_XMLAttribute *attributes, u32 nb_attributes)
{
	u32 i;
	if (!strcmp(name, "LASeRHeader")) {
		GF_ESD *esd;
		GF_LASERConfig *lsrc = (GF_LASERConfig *) gf_odf_desc_new(GF_ODF_LASER_CFG_TAG);
		for (i=0; i<nb_attributes; i++) {
			GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
			if (!strcmp(att->name, "profile")) lsrc->profile = !strcmp(att->value, "full") ? 1 : 0;
			else if (!strcmp(att->name, "level")) lsrc->level = atoi(att->value);
			else if (!strcmp(att->name, "resolution")) lsrc->resolution = atoi(att->value);
			else if (!strcmp(att->name, "timeResolution")) lsrc->time_resolution = atoi(att->value);
			else if (!strcmp(att->name, "coordBits")) lsrc->coord_bits = atoi(att->value);
			else if (!strcmp(att->name, "scaleBits_minus_coordBits")) lsrc->scale_bits_minus_coord_bits = atoi(att->value);
			else if (!strcmp(att->name, "colorComponentBits")) lsrc->colorComponentBits = atoi(att->value);
			else if (!strcmp(att->name, "newSceneIndicator")) lsrc->newSceneIndicator = (!strcmp(att->value, "yes") || !strcmp(att->value, "true")) ? 1 : 0;
			else if (!strcmp(att->name, "useFullRequestHost")) lsrc->fullRequestHost = (!strcmp(att->value, "yes") || !strcmp(att->value, "true")) ? 1 : 0;
			else if (!strcmp(att->name, "pathComponents")) lsrc->fullRequestHost = atoi(att->value);
			else if (!strcmp(att->name, "extensionIDBits")) lsrc->extensionIDBits = atoi(att->value);
			/*others are ignored in GPAC atm*/
		}
		esd = gf_odf_desc_esd_new(2);
		gf_odf_desc_del((GF_Descriptor *)esd->decoderConfig->decoderSpecificInfo);
		esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) lsrc;
		esd->decoderConfig->streamType = GF_STREAM_SCENE;
		esd->decoderConfig->objectTypeIndication = GF_CODECID_LASER;
		esd->slConfig->timestampResolution = lsrc->time_resolution ? lsrc->time_resolution : 1000;
		return esd;
	}
	return NULL;
}


GF_Err tpay_box_dump(GF_Box *a, FILE * trace)
{
	GF_TPAYBox *p;
	p = (GF_TPAYBox *)a;
	gf_isom_box_dump_start(a, "TotalMediaBytesBox", trace);
	gf_fprintf(trace, "BytesSent=\"%d\">\n", p->nbBytes);
	gf_isom_box_dump_done("TotalMediaBytesBox", a, trace);
	return GF_OK;
}


GF_Err iSFM_box_dump(GF_Box *a, FILE * trace)
{
	GF_ISMASampleFormatBox *p;
	const char *name = (a->type==GF_ISOM_BOX_TYPE_ISFM) ? "ISMASampleFormat" : "OMADRMAUFormatBox";
	p = (GF_ISMASampleFormatBox *)a;
	gf_isom_box_dump_start(a, name, trace);
	gf_fprintf(trace, "selective_encryption=\"%d\" key_indicator_length=\"%d\" IV_length=\"%d\">\n", p->selective_encryption, p->key_indicator_length, p->IV_length);
	gf_isom_box_dump_done(name, a, trace);
	return GF_OK;
}


}
static JSValue js_sys_ntohs(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
	s64 val;
	if (!argc) return GF_JS_EXCEPTION(ctx);
	if (JS_ToInt64(ctx, &val, argv[0])) return GF_JS_EXCEPTION(ctx);
	return JS_NewInt32(ctx, gf_ntohs((u16) val));


GF_Err load_svg_parse_string(GF_SceneLoader *load, const char *str)
{
	GF_Err e;
	GF_SVG_Parser *parser = (GF_SVG_Parser *)load->loader_priv;

	if (!parser) {
		e = gf_sm_load_initialize_svg(load, str, GF_FALSE);
		parser = (GF_SVG_Parser *)load->loader_priv;
	} else {
		e = gf_xml_sax_parse(parser->sax_parser, str);
	}
	if (e<0) svg_report(parser, e, "Unable to parse chunk: %s", parser ? gf_xml_sax_get_error(parser->sax_parser) : "no parser");
	else e = parser->last_error;

	svg_flush_animations(parser);

	/*if error move to done state and wait for next XML chunk*/
	if (e) load_svg_done(load);

	return e;
}


GF_Err hnti_box_dump(GF_Box *a, FILE * trace)
{
	gf_isom_box_dump_start(a, "HintTrackInfoBox", trace);
	gf_fprintf(trace, ">\n");
	gf_isom_box_dump_done("HintTrackInfoBox", a, trace);
	return GF_OK;
}


static JSValue js_fileio_protect(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
	JSFileIOCtx *ioctx = JS_GetOpaque(this_val, fileio_class_id);
	if (!ioctx) return JS_UNDEFINED;
	if (!ioctx->factory->lock) {
		ioctx->factory->lock = GF_TRUE;
		ioctx->factory->all_refs++;
	}
	return JS_UNDEFINED;


JSValue js_print(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
	return js_print_ex(ctx, this_val, argc, argv, GF_LOG_CONSOLE, GF_FALSE);
}


			ctx->mpd->minimum_update_period = 0;
		}
	}
	dasher_check_chaining(ctx, "urn:mpeg:dash:mpd-chaining:2016", ctx->chain);
	dasher_check_chaining(ctx, "urn:mpeg:dash:fallback:2016", ctx->chain_fbk);
	return GF_OK;
}
static GF_Err dasher_setup_mpd(GF_DasherCtx *ctx)
{
	u32 i, count;
	GF_MPD_ProgramInfo *info;
	ctx->mpd = gf_mpd_new();
	ctx->mpd->xml_namespace = "urn:mpeg:dash:schema:mpd:2011";
	ctx->mpd->base_URLs = gf_list_new();
	ctx->mpd->locations = gf_list_new();
	ctx->mpd->program_infos = gf_list_new();
	ctx->mpd->periods = gf_list_new();
	//created by default because we store xmlns in it
	ctx->mpd->x_attributes = gf_list_new();
	if (ctx->buf<0) {
		s32 buf = -ctx->buf;
		ctx->mpd->min_buffer_time = (u32) ( ctx->segdur.num * 10 * buf / ctx->segdur.den); //*1000 (ms) / 100 (percent)
	} else
		ctx->mpd->min_buffer_time = ctx->buf;

	GF_SAFEALLOC(info, GF_MPD_ProgramInfo);
	if (info) {
		gf_list_add(ctx->mpd->program_infos, info);
		if (ctx->title)
			info->title = gf_strdup(ctx->title);
		else {
			char tmp[256];
			const char *name = NULL;
			if (ctx->out_path) {
				const char *url = ctx->out_path;
				if (!strncmp(ctx->out_path, "gfio://", 7)) {
					url = gf_fileio_translate_url(ctx->out_path);
					if (!url) url = "";
				}
				name = strrchr(url, '/');
				if (!name) name = strrchr(url, '\\');
				if (!name) name = url;
				else name++;
			}
			snprintf(tmp, 255, "%s generated by GPAC", name ? name : "");
			tmp[255]=0;
			info->title = gf_strdup(tmp);
		}
		if (ctx->cprt) info->copyright = gf_strdup(ctx->cprt);
		if (ctx->info) info->more_info_url = gf_strdup(ctx->info);
		else info->more_info_url = gf_strdup("http://gpac.io");
		if (ctx->source) info->source = gf_strdup(ctx->source);
		if (ctx->lang) info->lang = gf_strdup(ctx->lang);
	}

	count = ctx->location.nb_items;
	for (i=0; i<count; i++) {
		char *l = ctx->location.vals[i];
		gf_list_add(ctx->mpd->locations, gf_strdup(l));
	}
	count = ctx->base.nb_items;
	for (i=0; i<count; i++) {
		GF_MPD_BaseURL *base;
		char *b = ctx->base.vals[i];
		GF_SAFEALLOC(base, GF_MPD_BaseURL);


static void dump_data_string(FILE *trace, char *data, u32 dataLength)
{
	u32 i;
	for (i=0; i<dataLength; i++) {
		switch ((unsigned char) data[i]) {
		case '\'':
			gf_fprintf(trace, "'");
			break;
		case '\"':
			gf_fprintf(trace, """);
			break;
		case '&':
			gf_fprintf(trace, "&");
			break;
		case '>':
			gf_fprintf(trace, ">");
			break;
		case '<':
			gf_fprintf(trace, "<");
			break;
		default:
			gf_fprintf(trace, "%c", (u8) data[i]);
			break;
		}
	}
}


GF_Err adaf_box_dump(GF_Box *a, FILE * trace)
{
	GF_AdobeDRMAUFormatBox *ptr = (GF_AdobeDRMAUFormatBox *)a;
	if (!a) return GF_BAD_PARAM;
	gf_isom_box_dump_start(a, "AdobeDRMAUFormatBox ", trace);
	gf_fprintf(trace, "SelectiveEncryption=\"%d\" IV_length=\"%d\">\n", ptr->selective_enc ? 1 : 0, ptr->IV_length);
	gf_isom_box_dump_done("AdobeDRMAUFormatBox", a, trace);
	return GF_OK;
}


static GF_XMLNode *ttml_locate_div(GF_XMLNode *body, const char *region_name, u32 div_idx)
{
	u32 i=0, loc_div_idx=0;
	GF_XMLNode *div;
	while ( (div = gf_list_enum(body->content, &i)) ) {
		if (div->type) continue;
		if (strcmp(div->name, "div")) continue;

		if (!region_name) {
			if (div_idx==loc_div_idx) return div;
			loc_div_idx++;
		} else {
			GF_XMLAttribute *att = ttml_get_attr(div, "region");
			if (att && att->value && !strcmp(att->value, region_name))
				return div;
		}
	}
	if (region_name) {
		return ttml_locate_div(body, NULL, div_idx);
	}
	return NULL;
}


GF_Err gnra_box_dump(GF_Box *a, FILE * trace)
{
	GF_GenericAudioSampleEntryBox *p = (GF_GenericAudioSampleEntryBox *)a;
	if (p->EntryType)
		a->type = p->EntryType;

	gf_isom_box_dump_start(a, "AudioSampleDescriptionBox", trace);
	gf_fprintf(trace, "DataReferenceIndex=\"%d\" Version=\"%d\" Revision=\"%d\" Vendor=\"%d\" ChannelCount=\"%d\" BitsPerSample=\"%d\" Samplerate=\"%d\"",
	        p->dataReferenceIndex, p->version, p->revision, p->vendor, p->channel_count, p->bitspersample, p->samplerate_hi);

	a->type = GF_ISOM_BOX_TYPE_GNRA;
	gnr_dump_exts(p->data, p->data_size, trace);

	gf_isom_box_dump_done("AudioSampleDescriptionBox", a, trace);
	return GF_OK;
}


GF_Err audio_sample_entry_box_dump(GF_Box *a, FILE * trace)
{
	char *szName;
	const char *error=NULL;
	GF_MPEGAudioSampleEntryBox *p = (GF_MPEGAudioSampleEntryBox *)a;

	switch (p->type) {
	case GF_ISOM_SUBTYPE_3GP_AMR:
		szName = "AMRSampleDescriptionBox";
		if (!p->cfg_3gpp)
		 	error = "<!-- INVALID 3GPP FILE: Config not present in Sample Description-->";
		break;
	case GF_ISOM_SUBTYPE_3GP_AMR_WB:
		szName = "AMR_WB_SampleDescriptionBox";
		if (!p->cfg_3gpp)
		 	error = "<!-- INVALID 3GPP FILE: Config not present in Sample Description-->";
		break;
	case GF_ISOM_SUBTYPE_3GP_EVRC:
		szName = "EVRCSampleDescriptionBox";
		if (!p->cfg_3gpp)
		 	error = "<!-- INVALID 3GPP FILE: Config not present in Sample Description-->";
		break;
	case GF_ISOM_SUBTYPE_3GP_QCELP:
		szName = "QCELPSampleDescriptionBox";
		if (!p->cfg_3gpp)
		 	error = "<!-- INVALID 3GPP Entry: Config not present in Audio Sample Description-->";
		break;
	case GF_ISOM_SUBTYPE_3GP_SMV:
		szName = "SMVSampleDescriptionBox";
		if (!p->cfg_3gpp)
		 	error = "<!-- INVALID 3GPP Entry: Config not present in Audio Sample Description-->";
		break;
	case GF_ISOM_BOX_TYPE_MP4A:
		szName = "MPEGAudioSampleDescriptionBox";
		if (!p->esd)
		 	error = "<!--INVALID MP4 Entry: ESDBox not present in Audio Sample Description -->";
		break;
	case GF_ISOM_BOX_TYPE_AC3:
		szName = "AC3SampleEntryBox";
		if (!p->cfg_ac3)
		 	error = "<!--INVALID AC3 Entry: AC3Config not present in Audio Sample Description -->";
		break;
	case GF_ISOM_BOX_TYPE_EC3:
		szName = "EC3SampleEntryBox";
		if (!p->cfg_ac3)
		 	error = "<!--INVALID EC3 Entry: AC3Config not present in Audio Sample Description -->";
		break;
	case GF_ISOM_BOX_TYPE_MHA1:
	case GF_ISOM_BOX_TYPE_MHA2:
		if (!p->cfg_mha)
		 	error = "<!--INVALID MPEG-H 3D Audio Entry: MHA config not present in Audio Sample Description -->";
	case GF_ISOM_BOX_TYPE_MHM1:
	case GF_ISOM_BOX_TYPE_MHM2:
		szName = "MHASampleEntry";
		break;
	case GF_ISOM_BOX_TYPE_MLPA:
		if (!p->cfg_mlp)
		 	error = "<!--INVALID TrueHD Audio Entry: DMLP config not present in Audio Sample Description -->";
		szName = "TrueHDSampleEntry";
		break;
	default:
		szName = "AudioSampleDescriptionBox";
		break;
	}

	gf_isom_box_dump_start(a, szName, trace);
	base_audio_entry_dump((GF_AudioSampleEntryBox *)p, trace);
	gf_fprintf(trace, ">\n");

	if (error) {
		gf_fprintf(trace, "%s\n", error);
	}
	gf_isom_box_dump_done(szName, a, trace);
	return GF_OK;
}


GF_Err gf_isom_dump_hint_sample(GF_ISOFile *the_file, u32 trackNumber, u32 SampleNum, FILE * trace)
{
	GF_ISOSample *tmp;
	GF_HintSampleEntryBox *entry;
	u32 descIndex, count, count2, i;
	GF_Err e=GF_OK;
	GF_BitStream *bs;
	GF_HintSample *s;
	GF_TrackBox *trak;
	GF_RTPPacket *pck;
	char *szName;

	trak = gf_isom_get_track_from_file(the_file, trackNumber);
	if (!trak || !IsHintTrack(trak)) return GF_BAD_PARAM;

	tmp = gf_isom_get_sample(the_file, trackNumber, SampleNum, &descIndex);
	if (!tmp) return GF_BAD_PARAM;

	e = Media_GetSampleDesc(trak->Media, descIndex, (GF_SampleEntryBox **) &entry, &count);
	if (e) {
		gf_isom_sample_del(&tmp);
		return e;
	}

	//check we can read the sample
	switch (entry->type) {
	case GF_ISOM_BOX_TYPE_RTP_STSD:
	case GF_ISOM_BOX_TYPE_SRTP_STSD:
	case GF_ISOM_BOX_TYPE_RRTP_STSD:
		szName = "RTP";
		break;
	case GF_ISOM_BOX_TYPE_RTCP_STSD:
		szName = "RCTP";
		break;
	case GF_ISOM_BOX_TYPE_FDP_STSD:
		szName = "FDP";
		break;
	default:
		gf_isom_sample_del(&tmp);
		return GF_NOT_SUPPORTED;
	}

	bs = gf_bs_new(tmp->data, tmp->dataLength, GF_BITSTREAM_READ);
	s = gf_isom_hint_sample_new(entry->type);
	s->trackID = trak->Header->trackID;
	s->sampleNumber = SampleNum;

	gf_isom_hint_sample_read(s, bs, tmp->dataLength);
	gf_bs_del(bs);

	count = gf_list_count(s->packetTable);

	gf_fprintf(trace, "<%sHintSample SampleNumber=\"%d\" DecodingTime=\""LLD"\" RandomAccessPoint=\"%d\" PacketCount=\"%u\" reserved=\"%u\">\n", szName, SampleNum, tmp->DTS, tmp->IsRAP, s->packetCount, s->reserved);

	if (s->hint_subtype==GF_ISOM_BOX_TYPE_FDP_STSD) {
		e = gf_isom_box_dump((GF_Box*) s, trace);
		goto err_exit;
	}

	if (s->packetCount != count) {
		gf_fprintf(trace, "<!-- WARNING: Broken %s hint sample, %d entries indicated but only %d parsed -->\n", szName, s->packetCount, count);
	}

	for (i=0; i<count; i++) {
		pck = (GF_RTPPacket *)gf_list_get(s->packetTable, i);

		if (pck->hint_subtype==GF_ISOM_BOX_TYPE_RTCP_STSD) {
			GF_RTCPPacket *rtcp_pck = (GF_RTCPPacket *) pck;
			gf_fprintf(trace, "<RTCPHintPacket PacketNumber=\"%d\" V=\"%d\" P=\"%d\" Count=\"%d\" PayloadType=\"%d\" ",
		        i+1,  rtcp_pck->Version, rtcp_pck->Padding, rtcp_pck->Count, rtcp_pck->PayloadType);

			if (rtcp_pck->data) dump_data_attribute(trace, "payload", (char*)rtcp_pck->data, rtcp_pck->length);
			gf_fprintf(trace, ">\n");
			gf_fprintf(trace, "</RTCPHintPacket>\n");

		} else {
			gf_fprintf(trace, "<RTPHintPacket PacketNumber=\"%d\" P=\"%d\" X=\"%d\" M=\"%d\" PayloadType=\"%d\"",
		        i+1,  pck->P_bit, pck->X_bit, pck->M_bit, pck->payloadType);

			gf_fprintf(trace, " SequenceNumber=\"%d\" RepeatedPacket=\"%d\" DropablePacket=\"%d\" RelativeTransmissionTime=\"%d\" FullPacketSize=\"%d\">\n",
		        pck->SequenceNumber, pck->R_bit, pck->B_bit, pck->relativeTransTime, gf_isom_hint_rtp_length(pck));

			//TLV is made of Boxes
			count2 = gf_list_count(pck->TLV);
			if (count2) {
				gf_fprintf(trace, "<PrivateExtensionTable EntryCount=\"%d\">\n", count2);
				gf_fprintf(trace, "</PrivateExtensionTable>\n");
			}
			//DTE is made of NON boxes
			count2 = gf_list_count(pck->DataTable);
			if (count2) {
				gf_fprintf(trace, "<PacketDataTable EntryCount=\"%d\">\n", count2);
				DTE_Dump(pck->DataTable, trace);
				gf_fprintf(trace, "</PacketDataTable>\n");
			}
			gf_fprintf(trace, "</RTPHintPacket>\n");
		}
	}

err_exit:
	gf_fprintf(trace, "</%sHintSample>\n", szName);
	gf_isom_sample_del(&tmp);
	gf_isom_hint_sample_del(s);
	return e;
}


GF_Err asrt_box_dump(GF_Box *a, FILE * trace)
{
	u32 i;
	GF_AdobeSegmentRunTableBox *p = (GF_AdobeSegmentRunTableBox*)a;
	gf_isom_box_dump_start(a, "AdobeSegmentRunTableBox", trace);

	gf_fprintf(trace, ">\n");

	for (i=0; i<p->quality_entry_count; i++) {
		char *str = (char*)gf_list_get(p->quality_segment_url_modifiers, i);
		gf_fprintf(trace, "<QualityEntry>%s</QualityEntry>\n", str);
	}

	for (i=0; i<p->segment_run_entry_count; i++) {
		GF_AdobeSegmentRunEntry *sre = (GF_AdobeSegmentRunEntry *)gf_list_get(p->segment_run_entry_table, i);
		gf_fprintf(trace, "<SegmentRunEntry FirstSegment=\"%u\" FragmentsPerSegment=\"%u\"/>\n", sre->first_segment, sre->fragment_per_segment);
	}

	gf_isom_box_dump_done("AdobeSegmentRunTableBox", a, trace);
	return GF_OK;
}


static JSValue js_bs_get_u16(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
	GET_JSBS
	if (!bs) return GF_JS_EXCEPTION(ctx);
	return JS_NewInt32(ctx, gf_bs_read_u16(bs) );
}


static void cryptinfo_text(void *sax_cbck, const char *text, Bool is_cdata)
{
	u32 len, len2;
	GF_TrackCryptInfo *tkc;
	GF_CryptInfo *info = (GF_CryptInfo *)sax_cbck;

	if (!info->in_text_header) return;

	tkc = (GF_TrackCryptInfo *) gf_list_last(info->tcis);
	len = (u32) strlen(text);
	len2 = tkc->TextualHeaders ? (u32) strlen(tkc->TextualHeaders) : 0;

	tkc->TextualHeaders = gf_realloc(tkc->TextualHeaders, sizeof(char) * (len+len2+1));
	if (!len2) strcpy(tkc->TextualHeaders, "");
	strcat(tkc->TextualHeaders, text);
}


GF_Err saiz_box_dump(GF_Box *a, FILE * trace)
{
	u32 i;
	GF_SampleAuxiliaryInfoSizeBox *ptr = (GF_SampleAuxiliaryInfoSizeBox*) a;
	if (!a) return GF_BAD_PARAM;

	if (dump_skip_samples)
		return GF_OK;

	gf_isom_box_dump_start(a, "SampleAuxiliaryInfoSizeBox", trace);

	gf_fprintf(trace, "default_sample_info_size=\"%d\" sample_count=\"%d\"", ptr->default_sample_info_size, ptr->sample_count);
	if (ptr->flags & 1) {
		if (isalnum(ptr->aux_info_type>>24)) {
			gf_fprintf(trace, " aux_info_type=\"%s\" aux_info_type_parameter=\"%d\"", gf_4cc_to_str(ptr->aux_info_type), ptr->aux_info_type_parameter);
		} else {
			gf_fprintf(trace, " aux_info_type=\"%d\" aux_info_type_parameter=\"%d\"", ptr->aux_info_type, ptr->aux_info_type_parameter);
		}
	}
	gf_fprintf(trace, ">\n");
	if (ptr->default_sample_info_size==0) {
		for (i=0; i<ptr->sample_count; i++) {
			gf_fprintf(trace, "<SAISize size=\"%d\" />\n", ptr->sample_info_size[i]);
		}
	}
	if (!ptr->size) {
			gf_fprintf(trace, "<SAISize size=\"\" />\n");
	}
	gf_isom_box_dump_done("SampleAuxiliaryInfoSizeBox", a, trace);
	return GF_OK;
}


GF_Err odrb_box_dump(GF_Box *a, FILE * trace)
{
	GF_OMADRMRightsObjectBox*ptr = (GF_OMADRMRightsObjectBox*)a;
	gf_isom_box_dump_start(a, "OMADRMRightsObjectBox", trace);

	gf_fprintf(trace, "OMARightsObject=\"");
	dump_data(trace, ptr->oma_ro, ptr->oma_ro_size);
	gf_fprintf(trace, "\">\n");
	gf_isom_box_dump_done("OMADRMRightsObjectBox", a, trace);
	return GF_OK;
}


static void nhmldump_send_dims(GF_NHMLDumpCtx *ctx, char *data, u32 data_size, GF_FilterPacket *pck)
{
	char nhml[1024];
	u32 size;
	u8 *output;
	GF_FilterPacket *dst_pck;
	u64 dts = gf_filter_pck_get_dts(pck);
	u64 cts = gf_filter_pck_get_cts(pck);

	if (dts==GF_FILTER_NO_TS) dts = cts;
	if (cts==GF_FILTER_NO_TS) cts = dts;

	if (!ctx->bs_r) ctx->bs_r = gf_bs_new(data, data_size, GF_BITSTREAM_READ);
	else gf_bs_reassign_buffer(ctx->bs_r, data, data_size);

	while (gf_bs_available(ctx->bs_r)) {
		u64 pos = gf_bs_get_position(ctx->bs_r);
		size = gf_bs_read_u16(ctx->bs_r);
		u8 flags = gf_bs_read_u8(ctx->bs_r);
		u8 prev;

		if (pos+size+2 > data_size)
			break;

		prev = 0;
		if (pos+2+size<data_size) {
			prev = data[pos+2+size];
			data[pos+2+size] = 0;
		}

		sprintf(nhml, "<DIMSUnit time=\""LLU"\"", cts);
		gf_bs_write_data(ctx->bs_w, nhml, (u32) strlen(nhml));

		/*DIMS flags*/
		if (flags & GF_DIMS_UNIT_S) {
			sprintf(nhml, " is-Scene=\"yes\"");
			gf_bs_write_data(ctx->bs_w, nhml, (u32) strlen(nhml));
		}
		if (flags & GF_DIMS_UNIT_M) {
			sprintf(nhml, " is-RAP=\"yes\"");
			gf_bs_write_data(ctx->bs_w, nhml, (u32) strlen(nhml));
		}
		if (flags & GF_DIMS_UNIT_I) {
			sprintf(nhml, " is-redundant=\"yes\"");
			gf_bs_write_data(ctx->bs_w, nhml, (u32) strlen(nhml));
		}
		if (flags & GF_DIMS_UNIT_D) {
			sprintf(nhml, " redundant-exit=\"yes\"");
			gf_bs_write_data(ctx->bs_w, nhml, (u32) strlen(nhml));
		}
		if (flags & GF_DIMS_UNIT_P) {
			sprintf(nhml, " priority=\"high\"");
			gf_bs_write_data(ctx->bs_w, nhml, (u32) strlen(nhml));
		}
		if (flags & GF_DIMS_UNIT_C) {
			sprintf(nhml, " compressed=\"yes\"");
			gf_bs_write_data(ctx->bs_w, nhml, (u32) strlen(nhml));
		}
		sprintf(nhml, ">");
		gf_bs_write_data(ctx->bs_w, nhml, (u32) strlen(nhml));
		if (ctx->uncompress && (flags & GF_DIMS_UNIT_C)) {
#ifndef GPAC_DISABLE_ZLIB
			char svg_data[2049];
			int err;
			u32 done = 0;
			z_stream d_stream;
			d_stream.zalloc = (alloc_func)0;
			d_stream.zfree = (free_func)0;
			d_stream.opaque = (voidpf)0;
			d_stream.next_in  = (Bytef*) data+pos+3;
			d_stream.avail_in = size-1;
			d_stream.next_out = (Bytef*)svg_data;
			d_stream.avail_out = 2048;

			err = inflateInit(&d_stream);
			if (err == Z_OK) {
				while ((s32) d_stream.total_in < size-1) {
					err = inflate(&d_stream, Z_NO_FLUSH);
					if (err < Z_OK) break;
					svg_data[d_stream.total_out - done] = 0;
					gf_bs_write_data(ctx->bs_w, svg_data, (u32) strlen(svg_data));

					if (err== Z_STREAM_END) break;
					done = (u32) d_stream.total_out;
					d_stream.avail_out = 2048;
					d_stream.next_out = (Bytef*)svg_data;
				}
				inflateEnd(&d_stream);
			}
#else
			GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("Error: your version of GPAC was compiled with no libz support."));
			gf_bs_del(ctx->bs_r);
			if (prev)
				data[pos+2+size] = prev;
			return;
#endif
		} else {
			gf_bs_write_data(ctx->bs_w, data+pos+3, size-1);
		}
		sprintf(nhml, "</DIMSUnit>\n");
		gf_bs_write_data(ctx->bs_w, nhml, (u32) strlen(nhml));

		if (prev)
			data[pos+2+size] = prev;
		gf_bs_skip_bytes(ctx->bs_r, size-1);
	}

	gf_bs_get_content_no_truncate(ctx->bs_w, &ctx->nhml_buffer, &size, &ctx->nhml_buffer_size);

	if (ctx->filep) {
		gf_fwrite(ctx->nhml_buffer, size, ctx->filep);
		return;
	}

	dst_pck = gf_filter_pck_new_alloc(ctx->opid_nhml, size, &output);
	if (!dst_pck) return;

	memcpy(output, ctx->nhml_buffer, size);
	gf_filter_pck_set_framing(dst_pck, GF_FALSE, GF_FALSE);
	gf_filter_pck_send(dst_pck);
}


static JSValue js_sys_compress_ex(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, Bool is_decomp)
{
	const u8 *data;
	size_t data_size;
	u32 out_size=0;
	u8 *out_ptr = NULL;
	JSValue res;
	GF_Err e;
	if (!argc || !JS_IsObject(argv[0])) return GF_JS_EXCEPTION(ctx);
	data = JS_GetArrayBuffer(ctx, &data_size, argv[0] );
	if (!data) return GF_JS_EXCEPTION(ctx);
	if (is_decomp) {
		e = gf_gz_decompress_payload((u8*) data, (u32) data_size, &out_ptr, &out_size);
	} else {
		e = gf_gz_compress_payload_ex((u8 **)&data, (u32) data_size, &out_size, 0, GF_FALSE, &out_ptr);
	}

	if (e) return js_throw_err(ctx, e);
	res = JS_NewArrayBuffer(ctx, out_ptr, out_size, js_gpac_free, NULL, 0);
	return res;
}


			gf_list_add(res, desc);
		}
	}
	gf_bs_del(bs_r);
	return res;
}

static void dasher_get_mime_and_ext(GF_DasherCtx *ctx, GF_DashStream *ds, const char **out_subtype, const char **out_ext)
{
	const char *subtype = NULL;
	const char *mux_ext = NULL;
	const char *cstr;

	if (ctx->muxtype!=DASHER_MUX_AUTO) {
		switch (ctx->muxtype) {
		case DASHER_MUX_ISOM: subtype = "mp4"; mux_ext = "mp4"; break;
		case DASHER_MUX_TS: subtype = "mp2t"; mux_ext = "ts"; break;
		case DASHER_MUX_MKV: subtype = "x-matroska"; mux_ext = "mkv"; break;
		case DASHER_MUX_WEBM: subtype = "webm"; mux_ext = "webm"; break;
		case DASHER_MUX_OGG: subtype = "ogg"; mux_ext = "ogg"; break;
		case DASHER_MUX_RAW:
			cstr = gf_codecid_mime(ds->codec_id);
			if (cstr) {
				subtype = strchr(cstr, '/');
				if (subtype) subtype++;
				else subtype = "raw";
			}
			if (out_ext) {
				cstr = gf_codecid_file_ext(ds->codec_id);
				if (cstr) *out_ext = cstr;
			}
			break;
		}
	} else if (ctx->initext) {
		mux_ext = ctx->initext;
		if (!strcmp(ctx->initext, "ts") || !strcmp(ctx->initext, "m2ts")) {
			subtype = "mp2t";
			ctx->muxtype = DASHER_MUX_TS;
		} else if (!strcmp(ctx->initext, "mkv") || !strcmp(ctx->initext, "mka") || !strcmp(ctx->initext, "mks") || !strcmp(ctx->initext, "mk3d")) {
			subtype = "x-matroska";
			ctx->muxtype = DASHER_MUX_MKV;
		} else if (!strcmp(ctx->initext, "webm") || !strcmp(ctx->initext, "weba")) {
			subtype = "webm";
			ctx->muxtype = DASHER_MUX_WEBM;
		} else if (!strcmp(ctx->initext, "ogg") || !strcmp(ctx->initext, "oga") || !strcmp(ctx->initext, "ogv") || !strcmp(ctx->initext, "spx") || !strcmp(ctx->initext, "oggm") || !strcmp(ctx->initext, "opus")) {
			subtype = "ogg";
			ctx->muxtype = DASHER_MUX_OGG;
		}
		else if (!strcmp(ctx->initext, "null")) {
			mux_ext = "mp4";
			ctx->muxtype = DASHER_MUX_ISOM;


			ctx->template = new_template;
		}

	}
	return GF_OK;
}

static GF_Err dasher_initialize(GF_Filter *filter)
{
	GF_Err e;
	GF_DasherCtx *ctx = gf_filter_get_udta(filter);
	gf_filter_set_max_extra_input_pids(filter, -1);

	ctx->pids = gf_list_new();
	ctx->postponed_pids = gf_list_new();
	ctx->tpl_records = gf_list_new();

	if (!ctx->initext && (ctx->muxtype==DASHER_MUX_AUTO))
		ctx->muxtype = DASHER_MUX_ISOM;

	if ((ctx->segdur.num <= 0) || !ctx->segdur.den) {
		ctx->segdur.num = 1;
		ctx->segdur.den = 1;
		ctx->no_seg_dur = GF_TRUE;
	}

	e = dasher_setup_profile(ctx);
	if (e) return e;

	if (ctx->sfile && ctx->tpl)
		ctx->tpl = GF_FALSE;

	ctx->current_period = dasher_new_period();
	ctx->next_period = dasher_new_period();
	ctx->on_demand_done = GF_TRUE;

	if (ctx->state) {
		ctx->first_context_load = GF_TRUE;
	}
	if (ctx->subdur && !ctx->state) {
		GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] subdur mode specified but no context set, will only dash %g seconds of media\n", ctx->subdur));
	}
	//we build manifest from input frag/seg, always use single frag
	if (ctx->sigfrag) {
		if (ctx->tpl) {
			ctx->sseg = GF_FALSE;
			ctx->sfile = GF_FALSE;
		} else {
			if (!ctx->sseg)
				ctx->sfile = GF_TRUE;
		}
		if (ctx->gencues) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("[Dasher] `sigfrag` and `gencues` options cannot be used together, disabling gencies\n"));
			ctx->gencues = GF_FALSE;
		}
	}

	if (!ctx->sap || ctx->sigfrag || ctx->cues)
		ctx->sbound = DASHER_BOUNDS_OUT;

	if ((ctx->tsb>=0) && (ctx->dmode!=GF_DASH_STATIC))
		ctx->purge_segments = GF_TRUE;

	if (ctx->state && ctx->sreg) {
		u32 diff;
		u64 next_gen_ntp;
		GF_Err dash_state_check_timing(const char *dash_state, u64 *next_gen_ntp_ms, u32 *next_time_ms);

		e = dash_state_check_timing(ctx->state, &next_gen_ntp, &diff);
		if (e<0) return e;


GF_Err piff_pssh_box_dump(GF_Box *a, FILE * trace)
{
	GF_PIFFProtectionSystemHeaderBox *ptr = (GF_PIFFProtectionSystemHeaderBox*) a;
	if (!a) return GF_BAD_PARAM;

	gf_isom_box_dump_start(a, "PIFFProtectionSystemHeaderBox", trace);
	fprintf(trace, "Version=\"%d\" Flags=\"%d\" ", ptr->version, ptr->flags);

	gf_fprintf(trace, "SystemID=\"");
	dump_data_hex(trace, (char *) ptr->SystemID, 16);
	gf_fprintf(trace, "\" PrivateData=\"");
	dump_data_hex(trace, (char *) ptr->private_data, ptr->private_data_size);
	gf_fprintf(trace, "\">\n");
	gf_isom_box_dump_done("PIFFProtectionSystemHeaderBox", a, trace);
	return GF_OK;
}


static JSValue js_bs_get_u24(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
	GET_JSBS
	if (!bs) return GF_JS_EXCEPTION(ctx);
	return JS_NewInt32(ctx, gf_bs_read_u24(bs) );
}


static GF_Node *svg_find_node(GF_SVG_Parser *parser, char *ID)
{
	u32 i, count, tag;
	char *node_class;
	GF_Node *n = gf_sg_find_node_by_name(parser->load->scene_graph, ID);
	if (n) return n;

	count = gf_list_count(parser->peeked_nodes);
	for (i=0; i<count; i++) {
		n = (GF_Node*)gf_list_get(parser->peeked_nodes, i);
		if (!strcmp(gf_node_get_name(n), ID)) return n;
	}
	node_class = gf_xml_sax_peek_node(parser->sax_parser, "id", ID, NULL, NULL, NULL, NULL);
	if (!node_class) return NULL;

	tag = gf_xml_get_element_tag(node_class, parser->current_ns);
	n = gf_node_new(parser->load->scene_graph, tag);

	gf_free(node_class);

	if (n) {
		gf_svg_parse_element_id(n, ID, GF_FALSE);
		gf_list_add(parser->peeked_nodes, n);
	}
	return n;
}