unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
{
	struct sock *sk = sock->sk;
	struct atm_vcc *vcc;
	unsigned int mask;

	sock_poll_wait(file, sk_sleep(sk), wait);
	mask = 0;

	vcc = ATM_SD(sock);

	/* exceptional events */
	if (sk->sk_err)
		mask = POLLERR;

	if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
	    test_bit(ATM_VF_CLOSE, &vcc->flags))
		mask |= POLLHUP;

	/* readable? */
	if (!skb_queue_empty(&sk->sk_receive_queue))
		mask |= POLLIN | POLLRDNORM;

	/* writable? */
	if (sock->state == SS_CONNECTING &&
	    test_bit(ATM_VF_WAITING, &vcc->flags))
		return mask;

	if (vcc->qos.txtp.traffic_class != ATM_NONE &&
	    vcc_writable(sk))
		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;

	return mask;
}


static u64 vmci_transport_stream_rcvhiwat(struct vsock_sock *vsk)
{
	return vmci_trans(vsk)->consume_size;
}


int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
			       struct msghdr *msg, size_t size, int flags)
{
	struct sock *sk = sock->sk;
	int err = 0;
	size_t target, copied = 0;
	long timeo;

	if (flags & MSG_OOB)
		return -EOPNOTSUPP;

	BT_DBG("sk %p size %zu", sk, size);

	lock_sock(sk);

	target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
	timeo  = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);

	do {
		struct sk_buff *skb;
		int chunk;

		skb = skb_dequeue(&sk->sk_receive_queue);
		if (!skb) {
			if (copied >= target)
				break;

			err = sock_error(sk);
			if (err)
				break;
			if (sk->sk_shutdown & RCV_SHUTDOWN)
				break;

			err = -EAGAIN;
			if (!timeo)
				break;

			timeo = bt_sock_data_wait(sk, timeo);

			if (signal_pending(current)) {
				err = sock_intr_errno(timeo);
				goto out;
			}
			continue;
		}

		chunk = min_t(unsigned int, skb->len, size);
		if (skb_copy_datagram_iovec(skb, 0, msg->msg_iov, chunk)) {
			skb_queue_head(&sk->sk_receive_queue, skb);
			if (!copied)
				copied = -EFAULT;
			break;
		}
		copied += chunk;
		size   -= chunk;

		sock_recv_ts_and_drops(msg, sk, skb);

		if (!(flags & MSG_PEEK)) {
			int skb_len = skb_headlen(skb);

			if (chunk <= skb_len) {
				__skb_pull(skb, chunk);
			} else {
				struct sk_buff *frag;

				__skb_pull(skb, skb_len);
				chunk -= skb_len;

				skb_walk_frags(skb, frag) {
					if (chunk <= frag->len) {
						/* Pulling partial data */
						skb->len -= chunk;
						skb->data_len -= chunk;
						__skb_pull(frag, chunk);
						break;
					} else if (frag->len) {
						/* Pulling all frag data */
						chunk -= frag->len;
						skb->len -= frag->len;
						skb->data_len -= frag->len;
						__skb_pull(frag, frag->len);
					}
				}
			}

			if (skb->len) {
				skb_queue_head(&sk->sk_receive_queue, skb);
				break;
			}
			kfree_skb(skb);

		} else {
			/* put message back and return */
			skb_queue_head(&sk->sk_receive_queue, skb);
			break;
		}
	} while (size);

out:
	release_sock(sk);
	return copied ? : err;
}


void bt_accept_unlink(struct sock *sk)
{
	BT_DBG("sk %p state %d", sk, sk->sk_state);

	list_del_init(&bt_sk(sk)->accept_q);
	bt_sk(sk)->parent->sk_ack_backlog--;
	bt_sk(sk)->parent = NULL;
	sock_put(sk);
}


static int get_name(struct socket *sock, struct sockaddr *uaddr,
		    int *uaddr_len, int peer)
{
	struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
	struct tipc_sock *tsock = tipc_sk(sock->sk);

	memset(addr, 0, sizeof(*addr));
	if (peer) {
		if ((sock->state != SS_CONNECTED) &&
			((peer != 2) || (sock->state != SS_DISCONNECTING)))
			return -ENOTCONN;
		addr->addr.id.ref = tsock->peer_name.ref;
		addr->addr.id.node = tsock->peer_name.node;
	} else {
		addr->addr.id.ref = tsock->p->ref;
		addr->addr.id.node = tipc_own_addr;
	}

	*uaddr_len = sizeof(*addr);
	addr->addrtype = TIPC_ADDR_ID;
	addr->family = AF_TIPC;
	addr->scope = 0;
	addr->addr.name.domain = 0;

	return 0;
}


static void vcc_def_wakeup(struct sock *sk)
{
	struct socket_wq *wq;

	rcu_read_lock();
	wq = rcu_dereference(sk->sk_wq);
	if (wq_has_sleeper(wq))
		wake_up(&wq->wait);
	rcu_read_unlock();
}


mISDN_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
{
	struct timeval	tv;

	if (_pms(sk)->cmask & MISDN_TIME_STAMP) {
		skb_get_timestamp(skb, &tv);
		put_cmsg(msg, SOL_MISDN, MISDN_TIME_STAMP, sizeof(tv), &tv);
	}
}


__netlink_kernel_create(struct net *net, int unit, struct module *module,
			struct netlink_kernel_cfg *cfg)
{
	struct socket *sock;
	struct sock *sk;
	struct netlink_sock *nlk;
	struct listeners *listeners = NULL;
	struct mutex *cb_mutex = cfg ? cfg->cb_mutex : NULL;
	unsigned int groups;

	BUG_ON(!nl_table);

	if (unit < 0 || unit >= MAX_LINKS)
		return NULL;

	if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
		return NULL;

	/*
	 * We have to just have a reference on the net from sk, but don't
	 * get_net it. Besides, we cannot get and then put the net here.
	 * So we create one inside init_net and the move it to net.
	 */

	if (__netlink_create(&init_net, sock, cb_mutex, unit) < 0)
		goto out_sock_release_nosk;

	sk = sock->sk;
	sk_change_net(sk, net);

	if (!cfg || cfg->groups < 32)
		groups = 32;
	else
		groups = cfg->groups;

	listeners = kzalloc(sizeof(*listeners) + NLGRPSZ(groups), GFP_KERNEL);
	if (!listeners)
		goto out_sock_release;

	sk->sk_data_ready = netlink_data_ready;
	if (cfg && cfg->input)
		nlk_sk(sk)->netlink_rcv = cfg->input;

	if (netlink_insert(sk, net, 0))
		goto out_sock_release;

	nlk = nlk_sk(sk);
	nlk->flags |= NETLINK_KERNEL_SOCKET;

	netlink_table_grab();
	if (!nl_table[unit].registered) {
		nl_table[unit].groups = groups;
		rcu_assign_pointer(nl_table[unit].listeners, listeners);
		nl_table[unit].cb_mutex = cb_mutex;
		nl_table[unit].module = module;
		if (cfg) {
			nl_table[unit].bind = cfg->bind;
			nl_table[unit].flags = cfg->flags;
			if (cfg->compare)
				nl_table[unit].compare = cfg->compare;
		}
		nl_table[unit].registered = 1;
	} else {
		kfree(listeners);
		nl_table[unit].registered++;
	}
	netlink_table_ungrab();
	return sk;

out_sock_release:
	kfree(listeners);
	netlink_kernel_release(sk);
	return NULL;

out_sock_release_nosk:
	sock_release(sock);
	return NULL;
}


static void pppol2tp_session_destruct(struct sock *sk)
{
	struct l2tp_session *session = sk->sk_user_data;
	if (session) {
		sk->sk_user_data = NULL;
		BUG_ON(session->magic != L2TP_SESSION_MAGIC);
		l2tp_session_dec_refcount(session);
	}
	return;
}


static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
			      const struct xfrm_migrate *m, int num_bundles,
			      const struct xfrm_kmaddress *k)
{
	int i;
	int sasize_sel;
	int size = 0;
	int size_pol = 0;
	struct sk_buff *skb;
	struct sadb_msg *hdr;
	struct sadb_x_policy *pol;
	const struct xfrm_migrate *mp;

	if (type != XFRM_POLICY_TYPE_MAIN)
		return 0;

	if (num_bundles <= 0 || num_bundles > XFRM_MAX_DEPTH)
		return -EINVAL;

	if (k != NULL) {
		/* addresses for KM */
		size += PFKEY_ALIGN8(sizeof(struct sadb_x_kmaddress) +
				     pfkey_sockaddr_pair_size(k->family));
	}

	/* selector */
	sasize_sel = pfkey_sockaddr_size(sel->family);
	if (!sasize_sel)
		return -EINVAL;
	size += (sizeof(struct sadb_address) + sasize_sel) * 2;

	/* policy info */
	size_pol += sizeof(struct sadb_x_policy);

	/* ipsecrequests */
	for (i = 0, mp = m; i < num_bundles; i++, mp++) {
		/* old locator pair */
		size_pol += sizeof(struct sadb_x_ipsecrequest) +
			    pfkey_sockaddr_pair_size(mp->old_family);
		/* new locator pair */
		size_pol += sizeof(struct sadb_x_ipsecrequest) +
			    pfkey_sockaddr_pair_size(mp->new_family);
	}

	size += sizeof(struct sadb_msg) + size_pol;

	/* alloc buffer */
	skb = alloc_skb(size, GFP_ATOMIC);
	if (skb == NULL)
		return -ENOMEM;

	hdr = (struct sadb_msg *)skb_put(skb, sizeof(struct sadb_msg));
	hdr->sadb_msg_version = PF_KEY_V2;
	hdr->sadb_msg_type = SADB_X_MIGRATE;
	hdr->sadb_msg_satype = pfkey_proto2satype(m->proto);
	hdr->sadb_msg_len = size / 8;
	hdr->sadb_msg_errno = 0;
	hdr->sadb_msg_reserved = 0;
	hdr->sadb_msg_seq = 0;
	hdr->sadb_msg_pid = 0;

	/* Addresses to be used by KM for negotiation, if ext is available */
	if (k != NULL && (set_sadb_kmaddress(skb, k) < 0))
		goto err;

	/* selector src */
	set_sadb_address(skb, sasize_sel, SADB_EXT_ADDRESS_SRC, sel);

	/* selector dst */
	set_sadb_address(skb, sasize_sel, SADB_EXT_ADDRESS_DST, sel);

	/* policy information */
	pol = (struct sadb_x_policy *)skb_put(skb, sizeof(struct sadb_x_policy));
	pol->sadb_x_policy_len = size_pol / 8;
	pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
	pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
	pol->sadb_x_policy_dir = dir + 1;
	pol->sadb_x_policy_reserved = 0;
	pol->sadb_x_policy_id = 0;
	pol->sadb_x_policy_priority = 0;

	for (i = 0, mp = m; i < num_bundles; i++, mp++) {
		/* old ipsecrequest */
		int mode = pfkey_mode_from_xfrm(mp->mode);
		if (mode < 0)
			goto err;
		if (set_ipsecrequest(skb, mp->proto, mode,
				     (mp->reqid ?  IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_REQUIRE),
				     mp->reqid, mp->old_family,
				     &mp->old_saddr, &mp->old_daddr) < 0)
			goto err;

		/* new ipsecrequest */
		if (set_ipsecrequest(skb, mp->proto, mode,
				     (mp->reqid ? IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_REQUIRE),
				     mp->reqid, mp->new_family,
				     &mp->new_saddr, &mp->new_daddr) < 0)
			goto err;
	}

	/* broadcast migrate message to sockets */
	pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, &init_net);

	return 0;

err:
	kfree_skb(skb);
	return -EINVAL;
}


static void afiucv_hs_callback_txnotify(struct sk_buff *skb,
					enum iucv_tx_notify n)
{
	struct sock *isk = skb->sk;
	struct sock *sk = NULL;
	struct iucv_sock *iucv = NULL;
	struct sk_buff_head *list;
	struct sk_buff *list_skb;
	struct sk_buff *nskb;
	unsigned long flags;

	read_lock_irqsave(&iucv_sk_list.lock, flags);
	sk_for_each(sk, &iucv_sk_list.head)
		if (sk == isk) {
			iucv = iucv_sk(sk);
			break;
		}
	read_unlock_irqrestore(&iucv_sk_list.lock, flags);

	if (!iucv || sock_flag(sk, SOCK_ZAPPED))
		return;

	list = &iucv->send_skb_q;
	spin_lock_irqsave(&list->lock, flags);
	if (skb_queue_empty(list))
		goto out_unlock;
	list_skb = list->next;
	nskb = list_skb->next;
	while (list_skb != (struct sk_buff *)list) {
		if (skb_shinfo(list_skb) == skb_shinfo(skb)) {
			switch (n) {
			case TX_NOTIFY_OK:
				__skb_unlink(list_skb, list);
				kfree_skb(list_skb);
				iucv_sock_wake_msglim(sk);
				break;
			case TX_NOTIFY_PENDING:
				atomic_inc(&iucv->pendings);
				break;
			case TX_NOTIFY_DELAYED_OK:
				__skb_unlink(list_skb, list);
				atomic_dec(&iucv->pendings);
				if (atomic_read(&iucv->pendings) <= 0)
					iucv_sock_wake_msglim(sk);
				kfree_skb(list_skb);
				break;
			case TX_NOTIFY_UNREACHABLE:
			case TX_NOTIFY_DELAYED_UNREACHABLE:
			case TX_NOTIFY_TPQFULL: /* not yet used */
			case TX_NOTIFY_GENERALERROR:
			case TX_NOTIFY_DELAYED_GENERALERROR:
				__skb_unlink(list_skb, list);
				kfree_skb(list_skb);
				if (sk->sk_state == IUCV_CONNECTED) {
					sk->sk_state = IUCV_DISCONN;
					sk->sk_state_change(sk);
				}
				break;
			}
			break;
		}
		list_skb = nskb;
		nskb = nskb->next;
	}
out_unlock:
	spin_unlock_irqrestore(&list->lock, flags);

	if (sk->sk_state == IUCV_CLOSING) {
		if (skb_queue_empty(&iucv_sk(sk)->send_skb_q)) {
			sk->sk_state = IUCV_CLOSED;
			sk->sk_state_change(sk);
		}
	}

}


static void __sco_sock_close(struct sock *sk)
{
	BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);

	switch (sk->sk_state) {
	case BT_LISTEN:
		sco_sock_cleanup_listen(sk);
		break;

	case BT_CONNECTED:
	case BT_CONFIG:
		if (sco_pi(sk)->conn->hcon) {
			sk->sk_state = BT_DISCONN;
			sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
			hci_conn_drop(sco_pi(sk)->conn->hcon);
			sco_pi(sk)->conn->hcon = NULL;
		} else
			sco_chan_del(sk, ECONNRESET);
		break;

	case BT_CONNECT2:
	case BT_CONNECT:
	case BT_DISCONN:
		sco_chan_del(sk, ECONNRESET);
		break;

	default:
		sock_set_flag(sk, SOCK_ZAPPED);
		break;
	}
}


int vmci_transport_send_waiting_write(struct sock *sk,
				      struct vmci_transport_waiting_info *wait)
{
	return vmci_transport_send_control_pkt(
				sk, VMCI_TRANSPORT_PACKET_TYPE_WAITING_WRITE,
				0, 0, wait, VSOCK_PROTO_INVALID,
				VMCI_INVALID_HANDLE);
}


static int vmci_transport_recv_stream_cb(void *data, struct vmci_datagram *dg)
{
	struct sock *sk;
	struct sockaddr_vm dst;
	struct sockaddr_vm src;
	struct vmci_transport_packet *pkt;
	struct vsock_sock *vsk;
	bool bh_process_pkt;
	int err;

	sk = NULL;
	err = VMCI_SUCCESS;
	bh_process_pkt = false;

	/* Ignore incoming packets from contexts without sockets, or resources
	 * that aren't vsock implementations.
	 */

	if (!vmci_transport_stream_allow(dg->src.context, -1)
	    || vmci_transport_peer_rid(dg->src.context) != dg->src.resource)
		return VMCI_ERROR_NO_ACCESS;

	if (VMCI_DG_SIZE(dg) < sizeof(*pkt))
		/* Drop datagrams that do not contain full VSock packets. */
		return VMCI_ERROR_INVALID_ARGS;

	pkt = (struct vmci_transport_packet *)dg;

	/* Find the socket that should handle this packet.  First we look for a
	 * connected socket and if there is none we look for a socket bound to
	 * the destintation address.
	 */
	vsock_addr_init(&src, pkt->dg.src.context, pkt->src_port);
	vsock_addr_init(&dst, pkt->dg.dst.context, pkt->dst_port);

	sk = vsock_find_connected_socket(&src, &dst);
	if (!sk) {
		sk = vsock_find_bound_socket(&dst);
		if (!sk) {
			/* We could not find a socket for this specified
			 * address.  If this packet is a RST, we just drop it.
			 * If it is another packet, we send a RST.  Note that
			 * we do not send a RST reply to RSTs so that we do not
			 * continually send RSTs between two endpoints.
			 *
			 * Note that since this is a reply, dst is src and src
			 * is dst.
			 */
			if (vmci_transport_send_reset_bh(&dst, &src, pkt) < 0)
				pr_err("unable to send reset\n");

			err = VMCI_ERROR_NOT_FOUND;
			goto out;
		}
	}

	/* If the received packet type is beyond all types known to this
	 * implementation, reply with an invalid message.  Hopefully this will
	 * help when implementing backwards compatibility in the future.
	 */
	if (pkt->type >= VMCI_TRANSPORT_PACKET_TYPE_MAX) {
		vmci_transport_send_invalid_bh(&dst, &src);
		err = VMCI_ERROR_INVALID_ARGS;
		goto out;
	}

	/* This handler is privileged when this module is running on the host.
	 * We will get datagram connect requests from all endpoints (even VMs
	 * that are in a restricted context). If we get one from a restricted
	 * context then the destination socket must be trusted.
	 *
	 * NOTE: We access the socket struct without holding the lock here.
	 * This is ok because the field we are interested is never modified
	 * outside of the create and destruct socket functions.
	 */
	vsk = vsock_sk(sk);
	if (!vmci_transport_allow_dgram(vsk, pkt->dg.src.context)) {
		err = VMCI_ERROR_NO_ACCESS;
		goto out;
	}

	/* We do most everything in a work queue, but let's fast path the
	 * notification of reads and writes to help data transfer performance.
	 * We can only do this if there is no process context code executing
	 * for this socket since that may change the state.
	 */
	bh_lock_sock(sk);

	if (!sock_owned_by_user(sk)) {
		/* The local context ID may be out of date, update it. */
		vsk->local_addr.svm_cid = dst.svm_cid;

		if (sk->sk_state == SS_CONNECTED)
			vmci_trans(vsk)->notify_ops->handle_notify_pkt(
					sk, pkt, true, &dst, &src,
					&bh_process_pkt);
	}

	bh_unlock_sock(sk);

	if (!bh_process_pkt) {
		struct vmci_transport_recv_pkt_info *recv_pkt_info;

		recv_pkt_info = kmalloc(sizeof(*recv_pkt_info), GFP_ATOMIC);
		if (!recv_pkt_info) {
			if (vmci_transport_send_reset_bh(&dst, &src, pkt) < 0)
				pr_err("unable to send reset\n");

			err = VMCI_ERROR_NO_MEM;
			goto out;
		}

		recv_pkt_info->sk = sk;
		memcpy(&recv_pkt_info->pkt, pkt, sizeof(recv_pkt_info->pkt));
		INIT_WORK(&recv_pkt_info->work, vmci_transport_recv_pkt_work);

		schedule_work(&recv_pkt_info->work);
		/* Clear sk so that the reference count incremented by one of
		 * the Find functions above is not decremented below.  We need
		 * that reference count for the packet handler we've scheduled
		 * to run.
		 */
		sk = NULL;
	}

out:
	if (sk)
		sock_put(sk);

	return err;
}


static int ipx_create(struct net *net, struct socket *sock, int protocol,
		      int kern)
{
	int rc = -ESOCKTNOSUPPORT;
	struct sock *sk;

	if (!net_eq(net, &init_net))
		return -EAFNOSUPPORT;

	/*
	 * SPX support is not anymore in the kernel sources. If you want to
	 * ressurrect it, completing it and making it understand shared skbs,
	 * be fully multithreaded, etc, grab the sources in an early 2.5 kernel
	 * tree.
	 */
	if (sock->type != SOCK_DGRAM)
		goto out;

	rc = -ENOMEM;
	sk = sk_alloc(net, PF_IPX, GFP_KERNEL, &ipx_proto);
	if (!sk)
		goto out;

	sk_refcnt_debug_inc(sk);
	sock_init_data(sock, sk);
	sk->sk_no_check = 1;		/* Checksum off by default */
	sock->ops = &ipx_dgram_ops;
	rc = 0;
out:
	return rc;
}


static void vmci_transport_peer_attach_cb(u32 sub_id,
					  const struct vmci_event_data *e_data,
					  void *client_data)
{
	struct sock *sk = client_data;
	const struct vmci_event_payload_qp *e_payload;
	struct vsock_sock *vsk;

	e_payload = vmci_event_data_const_payload(e_data);

	vsk = vsock_sk(sk);

	/* We don't ask for delayed CBs when we subscribe to this event (we
	 * pass 0 as flags to vmci_event_subscribe()).  VMCI makes no
	 * guarantees in that case about what context we might be running in,
	 * so it could be BH or process, blockable or non-blockable.  So we
	 * need to account for all possible contexts here.
	 */
	local_bh_disable();
	bh_lock_sock(sk);

	/* XXX This is lame, we should provide a way to lookup sockets by
	 * qp_handle.
	 */
	if (vmci_handle_is_equal(vmci_trans(vsk)->qp_handle,
				 e_payload->handle)) {
		/* XXX This doesn't do anything, but in the future we may want
		 * to set a flag here to verify the attach really did occur and
		 * we weren't just sent a datagram claiming it was.
		 */
		goto out;
	}

out:
	bh_unlock_sock(sk);
	local_bh_enable();
}


int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
		   unsigned int flags, struct timespec *timeout)
{
	int fput_needed, err, datagrams;
	struct socket *sock;
	struct mmsghdr __user *entry;
	struct compat_mmsghdr __user *compat_entry;
	struct msghdr msg_sys;
	struct timespec end_time;

	if (timeout &&
	    poll_select_set_timeout(&end_time, timeout->tv_sec,
				    timeout->tv_nsec))
		return -EINVAL;

	datagrams = 0;

	sock = sockfd_lookup_light(fd, &err, &fput_needed);
	if (!sock)
		return err;

	err = sock_error(sock->sk);
	if (err)
		goto out_put;

	entry = mmsg;
	compat_entry = (struct compat_mmsghdr __user *)mmsg;

	while (datagrams < vlen) {
		/*
		 * No need to ask LSM for more than the first datagram.
		 */
		if (MSG_CMSG_COMPAT & flags) {
			err = ___sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
					     &msg_sys, flags & ~MSG_WAITFORONE,
					     datagrams);
			if (err < 0)
				break;
			err = __put_user(err, &compat_entry->msg_len);
			++compat_entry;
		} else {
			err = ___sys_recvmsg(sock,
					     (struct msghdr __user *)entry,
					     &msg_sys, flags & ~MSG_WAITFORONE,
					     datagrams);
			if (err < 0)
				break;
			err = put_user(err, &entry->msg_len);
			++entry;
		}

		if (err)
			break;
		++datagrams;

		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
		if (flags & MSG_WAITFORONE)
			flags |= MSG_DONTWAIT;

		if (timeout) {
			ktime_get_ts(timeout);
			*timeout = timespec_sub(end_time, *timeout);
			if (timeout->tv_sec < 0) {
				timeout->tv_sec = timeout->tv_nsec = 0;
				break;
			}

			/* Timeout, return less than vlen datagrams */
			if (timeout->tv_nsec == 0 && timeout->tv_sec == 0)
				break;
		}

		/* Out of band data, return right away */
		if (msg_sys.msg_flags & MSG_OOB)
			break;
	}

out_put:
	fput_light(sock->file, fput_needed);

	if (err == 0)
		return datagrams;

	if (datagrams != 0) {
		/*
		 * We may return less entries than requested (vlen) if the
		 * sock is non block and there aren't enough datagrams...
		 */
		if (err != -EAGAIN) {
			/*
			 * ... or  if recvmsg returns an error after we
			 * received some datagrams, where we record the
			 * error to return on the next call or if the
			 * app asks about it using getsockopt(SO_ERROR).
			 */
			sock->sk->sk_err = -err;
		}

		return datagrams;
	}

	return err;
}


static void netlink_queue_mmaped_skb(struct sock *sk, struct sk_buff *skb)
{
	struct nl_mmap_hdr *hdr;

	hdr = netlink_mmap_hdr(skb);
	hdr->nm_len	= skb->len;
	hdr->nm_group	= NETLINK_CB(skb).dst_group;
	hdr->nm_pid	= NETLINK_CB(skb).creds.pid;
	hdr->nm_uid	= from_kuid(sk_user_ns(sk), NETLINK_CB(skb).creds.uid);
	hdr->nm_gid	= from_kgid(sk_user_ns(sk), NETLINK_CB(skb).creds.gid);
	netlink_frame_flush_dcache(hdr);
	netlink_set_status(hdr, NL_MMAP_STATUS_VALID);

	NETLINK_CB(skb).flags |= NETLINK_SKB_DELIVERED;
	kfree_skb(skb);
}


static int netlink_autobind(struct socket *sock)
{
	struct sock *sk = sock->sk;
	struct net *net = sock_net(sk);
	struct netlink_table *table = &nl_table[sk->sk_protocol];
	struct nl_portid_hash *hash = &table->hash;
	struct hlist_head *head;
	struct sock *osk;
	s32 portid = task_tgid_vnr(current);
	int err;
	static s32 rover = -4097;

retry:
	cond_resched();
	netlink_table_grab();
	head = nl_portid_hashfn(hash, portid);
	sk_for_each(osk, head) {
		if (!table->compare(net, osk))
			continue;
		if (nlk_sk(osk)->portid == portid) {
			/* Bind collision, search negative portid values. */
			portid = rover--;
			if (rover > -4097)
				rover = -4097;
			netlink_table_ungrab();
			goto retry;
		}
	}
	netlink_table_ungrab();

	err = netlink_insert(sk, net, portid);
	if (err == -EADDRINUSE)
		goto retry;

	/* If 2 threads race to autobind, that is fine.  */
	if (err == -EBUSY)
		err = 0;

	return err;
}


static int netlink_dump(struct sock *sk)
{
	struct netlink_sock *nlk = nlk_sk(sk);
	struct netlink_callback *cb;
	struct sk_buff *skb = NULL;
	struct nlmsghdr *nlh;
	int len, err = -ENOBUFS;
	int alloc_size;

	mutex_lock(nlk->cb_mutex);
	if (!nlk->cb_running) {
		err = -EINVAL;
		goto errout_skb;
	}

	cb = &nlk->cb;
	alloc_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE);

	if (!netlink_rx_is_mmaped(sk) &&
	    atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
		goto errout_skb;
	skb = netlink_alloc_skb(sk, alloc_size, nlk->portid, GFP_KERNEL);
	if (!skb)
		goto errout_skb;
	netlink_skb_set_owner_r(skb, sk);

	len = cb->dump(skb, cb);

	if (len > 0) {
		mutex_unlock(nlk->cb_mutex);

		if (sk_filter(sk, skb))
			kfree_skb(skb);
		else
			__netlink_sendskb(sk, skb);
		return 0;
	}

	nlh = nlmsg_put_answer(skb, cb, NLMSG_DONE, sizeof(len), NLM_F_MULTI);
	if (!nlh)
		goto errout_skb;

	nl_dump_check_consistent(cb, nlh);

	memcpy(nlmsg_data(nlh), &len, sizeof(len));

	if (sk_filter(sk, skb))
		kfree_skb(skb);
	else
		__netlink_sendskb(sk, skb);

	if (cb->done)
		cb->done(cb);

	nlk->cb_running = false;
	mutex_unlock(nlk->cb_mutex);
	module_put(cb->module);
	consume_skb(cb->skb);
	return 0;

errout_skb:
	mutex_unlock(nlk->cb_mutex);
	kfree_skb(skb);
	return err;
}


static int packet_create(struct net *net, struct socket *sock, int protocol,
			 int kern)
{
	struct sock *sk;
	struct packet_sock *po;
	__be16 proto = (__force __be16)protocol; /* weird, but documented */
	int err;

	if (!ns_capable(net->user_ns, CAP_NET_RAW))
		return -EPERM;
	if (sock->type != SOCK_DGRAM && sock->type != SOCK_RAW &&
	    sock->type != SOCK_PACKET)
		return -ESOCKTNOSUPPORT;

	sock->state = SS_UNCONNECTED;

	err = -ENOBUFS;
	sk = sk_alloc(net, PF_PACKET, GFP_KERNEL, &packet_proto);
	if (sk == NULL)
		goto out;

	sock->ops = &packet_ops;
	if (sock->type == SOCK_PACKET)
		sock->ops = &packet_ops_spkt;

	sock_init_data(sock, sk);

	po = pkt_sk(sk);
	sk->sk_family = PF_PACKET;
	po->num = proto;

	sk->sk_destruct = packet_sock_destruct;
	sk_refcnt_debug_inc(sk);

	/*
	 *	Attach a protocol block
	 */

	spin_lock_init(&po->bind_lock);
	mutex_init(&po->pg_vec_lock);
	po->prot_hook.func = packet_rcv;

	if (sock->type == SOCK_PACKET)
		po->prot_hook.func = packet_rcv_spkt;

	po->prot_hook.af_packet_priv = sk;

	if (proto) {
		po->prot_hook.type = proto;
		register_prot_hook(sk);
	}

	mutex_lock(&net->packet.sklist_lock);
	sk_add_node_rcu(sk, &net->packet.sklist);
	mutex_unlock(&net->packet.sklist_lock);

	preempt_disable();
	sock_prot_inuse_add(net, &packet_proto, 1);
	preempt_enable();

	return 0;
out:
	return err;
}


static void netlink_rcv_wake(struct sock *sk)
{
	struct netlink_sock *nlk = nlk_sk(sk);

	if (skb_queue_empty(&sk->sk_receive_queue))
		clear_bit(NETLINK_CONGESTED, &nlk->state);
	if (!test_bit(NETLINK_CONGESTED, &nlk->state))
		wake_up_interruptible(&nlk->wait);
}


int vmci_transport_send_read_bh(struct sockaddr_vm *dst,
				struct sockaddr_vm *src)
{
	return vmci_transport_send_control_pkt_bh(
					dst, src,
					VMCI_TRANSPORT_PACKET_TYPE_READ, 0,
					0, NULL, VMCI_INVALID_HANDLE);
}


static void caif_read_lock(struct sock *sk)
{
	struct caifsock *cf_sk;
	cf_sk = container_of(sk, struct caifsock, sk);
	mutex_lock(&cf_sk->readlock);
}


vmci_transport_recv_connecting_client_invalid(struct sock *sk,
					      struct vmci_transport_packet *pkt)
{
	int err = 0;
	struct vsock_sock *vsk = vsock_sk(sk);

	if (vsk->sent_request) {
		vsk->sent_request = false;
		vsk->ignore_connecting_rst = true;

		err = vmci_transport_send_conn_request(
			sk, vmci_trans(vsk)->queue_pair_size);
		if (err < 0)
			err = vmci_transport_error_to_vsock_error(err);
		else
			err = 0;

	}

	return err;
}


static bool netlink_skb_is_mmaped(const struct sk_buff *skb)
{
	return NETLINK_CB(skb).flags & NETLINK_SKB_MMAPED;
}


int vm_sockets_get_local_cid(void)
{
	return transport->get_local_cid();
}


int compat_mc_getsockopt(struct sock *sock, int level, int optname,
	char __user *optval, int __user *optlen,
	int (*getsockopt)(struct sock *, int, int, char __user *, int __user *))
{
	struct compat_group_filter __user *gf32 = (void *)optval;
	struct group_filter __user *kgf;
	int __user	*koptlen;
	u32 interface, fmode, numsrc;
	int klen, ulen, err;

	if (optname != MCAST_MSFILTER)
		return getsockopt(sock, level, optname, optval, optlen);

	koptlen = compat_alloc_user_space(sizeof(*koptlen));
	if (!access_ok(VERIFY_READ, optlen, sizeof(*optlen)) ||
	    __get_user(ulen, optlen))
		return -EFAULT;

	/* adjust len for pad */
	klen = ulen + sizeof(*kgf) - sizeof(*gf32);

	if (klen < GROUP_FILTER_SIZE(0))
		return -EINVAL;

	if (!access_ok(VERIFY_WRITE, koptlen, sizeof(*koptlen)) ||
	    __put_user(klen, koptlen))
		return -EFAULT;

	/* have to allow space for previous compat_alloc_user_space, too */
	kgf = compat_alloc_user_space(klen+sizeof(*optlen));

	if (!access_ok(VERIFY_READ, gf32, __COMPAT_GF0_SIZE) ||
	    __get_user(interface, &gf32->gf_interface) ||
	    __get_user(fmode, &gf32->gf_fmode) ||
	    __get_user(numsrc, &gf32->gf_numsrc) ||
	    __put_user(interface, &kgf->gf_interface) ||
	    __put_user(fmode, &kgf->gf_fmode) ||
	    __put_user(numsrc, &kgf->gf_numsrc) ||
	    copy_in_user(&kgf->gf_group, &gf32->gf_group, sizeof(kgf->gf_group)))
		return -EFAULT;

	err = getsockopt(sock, level, optname, (char __user *)kgf, koptlen);
	if (err)
		return err;

	if (!access_ok(VERIFY_READ, koptlen, sizeof(*koptlen)) ||
	    __get_user(klen, koptlen))
		return -EFAULT;

	ulen = klen - (sizeof(*kgf)-sizeof(*gf32));

	if (!access_ok(VERIFY_WRITE, optlen, sizeof(*optlen)) ||
	    __put_user(ulen, optlen))
		return -EFAULT;

	if (!access_ok(VERIFY_READ, kgf, klen) ||
	    !access_ok(VERIFY_WRITE, gf32, ulen) ||
	    __get_user(interface, &kgf->gf_interface) ||
	    __get_user(fmode, &kgf->gf_fmode) ||
	    __get_user(numsrc, &kgf->gf_numsrc) ||
	    __put_user(interface, &gf32->gf_interface) ||
	    __put_user(fmode, &gf32->gf_fmode) ||
	    __put_user(numsrc, &gf32->gf_numsrc))
		return -EFAULT;
	if (numsrc) {
		int copylen;

		klen -= GROUP_FILTER_SIZE(0);
		copylen = numsrc * sizeof(gf32->gf_slist[0]);
		if (copylen > klen)
			copylen = klen;
		if (copy_in_user(gf32->gf_slist, kgf->gf_slist, copylen))
			return -EFAULT;
	}
	return err;
}


static int do_set_attach_filter(struct socket *sock, int level, int optname,
				char __user *optval, unsigned int optlen)
{
	struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval;
	struct sock_fprog __user *kfprog = compat_alloc_user_space(sizeof(struct sock_fprog));
	compat_uptr_t ptr;
	u16 len;

	if (!access_ok(VERIFY_READ, fprog32, sizeof(*fprog32)) ||
	    !access_ok(VERIFY_WRITE, kfprog, sizeof(struct sock_fprog)) ||
	    __get_user(len, &fprog32->len) ||
	    __get_user(ptr, &fprog32->filter) ||
	    __put_user(len, &kfprog->len) ||
	    __put_user(compat_ptr(ptr), &kfprog->filter))
		return -EFAULT;

	return sock_setsockopt(sock, level, optname, (char __user *)kfprog,
			      sizeof(struct sock_fprog));
}


static __net_init int pppoe_init_net(struct net *net)
{
	struct pppoe_net *pn = pppoe_pernet(net);
	struct proc_dir_entry *pde;

	rwlock_init(&pn->hash_lock);

	pde = proc_create("pppoe", S_IRUGO, net->proc_net, &pppoe_seq_fops);
#ifdef CONFIG_PROC_FS
	if (!pde)
		return -ENOMEM;
#endif

	return 0;
}


static int skcipher_alloc_sgl(struct sock *sk)
{
	struct alg_sock *ask = alg_sk(sk);
	struct skcipher_ctx *ctx = ask->private;
	struct skcipher_sg_list *sgl;
	struct scatterlist *sg = NULL;

	sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list);
	if (!list_empty(&ctx->tsgl))
		sg = sgl->sg;

	if (!sg || sgl->cur >= MAX_SGL_ENTS) {
		sgl = sock_kmalloc(sk, sizeof(*sgl) +
				       sizeof(sgl->sg[0]) * (MAX_SGL_ENTS + 1),
				   GFP_KERNEL);
		if (!sgl)
			return -ENOMEM;

		sg_init_table(sgl->sg, MAX_SGL_ENTS + 1);
		sgl->cur = 0;

		if (sg)
			scatterwalk_sg_chain(sg, MAX_SGL_ENTS + 1, sgl->sg);

		list_add_tail(&sgl->list, &ctx->tsgl);
	}

	return 0;
}


static void vcc_destroy_socket(struct sock *sk)
{
	struct atm_vcc *vcc = atm_sk(sk);
	struct sk_buff *skb;

	set_bit(ATM_VF_CLOSE, &vcc->flags);
	clear_bit(ATM_VF_READY, &vcc->flags);
	if (vcc->dev) {
		if (vcc->dev->ops->close)
			vcc->dev->ops->close(vcc);
		if (vcc->push)
			vcc->push(vcc, NULL); /* atmarpd has no push */
		module_put(vcc->owner);

		while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
			atm_return(vcc, skb->truesize);
			kfree_skb(skb);
		}

		module_put(vcc->dev->ops->owner);
		atm_dev_put(vcc->dev);
	}

	vcc_remove_socket(sk);
}


void hci_sock_dev_event(struct hci_dev *hdev, int event)
{
	struct hci_ev_si_device ev;

	BT_DBG("hdev %s event %d", hdev->name, event);

	/* Send event to monitor */
	if (atomic_read(&monitor_promisc)) {
		struct sk_buff *skb;

		skb = create_monitor_event(hdev, event);
		if (skb) {
			send_monitor_event(skb);
			kfree_skb(skb);
		}
	}

	/* Send event to sockets */
	ev.event  = event;
	ev.dev_id = hdev->id;
	hci_si_event(NULL, HCI_EV_SI_DEVICE, sizeof(ev), &ev);

	if (event == HCI_DEV_UNREG) {
		struct sock *sk;

		/* Detach sockets from device */
		read_lock(&hci_sk_list.lock);
		sk_for_each(sk, &hci_sk_list.head) {
			bh_lock_sock_nested(sk);
			if (hci_pi(sk)->hdev == hdev) {
				hci_pi(sk)->hdev = NULL;
				sk->sk_err = EPIPE;
				sk->sk_state = BT_OPEN;
				sk->sk_state_change(sk);

				hci_dev_put(hdev);
			}
			bh_unlock_sock(sk);
		}
		read_unlock(&hci_sk_list.lock);
	}
}


netlink_previous_frame(const struct netlink_ring *ring,
		       enum nl_mmap_status status)
{
	unsigned int prev;

	prev = ring->head ? ring->head - 1 : ring->frame_max;
	return netlink_lookup_frame(ring, prev, status);
}


void vcc_process_recv_queue(struct atm_vcc *vcc)
{
	struct sk_buff_head queue, *rq;
	struct sk_buff *skb, *tmp;
	unsigned long flags;

	__skb_queue_head_init(&queue);
	rq = &sk_atm(vcc)->sk_receive_queue;

	spin_lock_irqsave(&rq->lock, flags);
	skb_queue_splice_init(rq, &queue);
	spin_unlock_irqrestore(&rq->lock, flags);

	skb_queue_walk_safe(&queue, skb, tmp) {
		__skb_unlink(skb, &queue);
		vcc->push(vcc, skb);
	}
}


static int pfkey_register(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
{
	struct pfkey_sock *pfk = pfkey_sk(sk);
	struct sk_buff *supp_skb;

	if (hdr->sadb_msg_satype > SADB_SATYPE_MAX)
		return -EINVAL;

	if (hdr->sadb_msg_satype != SADB_SATYPE_UNSPEC) {
		if (pfk->registered&(1<<hdr->sadb_msg_satype))
			return -EEXIST;
		pfk->registered |= (1<<hdr->sadb_msg_satype);
	}

	xfrm_probe_algs();

	supp_skb = compose_sadb_supported(hdr, GFP_KERNEL);
	if (!supp_skb) {
		if (hdr->sadb_msg_satype != SADB_SATYPE_UNSPEC)
			pfk->registered &= ~(1<<hdr->sadb_msg_satype);

		return -ENOBUFS;
	}

	pfkey_broadcast(supp_skb, GFP_KERNEL, BROADCAST_REGISTERED, sk, sock_net(sk));

	return 0;
}


bool rxrpc_kernel_is_data_last(struct sk_buff *skb)
{
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);

	ASSERTCMP(skb->mark, ==, RXRPC_SKB_MARK_DATA);

	return sp->hdr.flags & RXRPC_LAST_PACKET;
}


static inline void high_nmcpy(unsigned char *dst, char *src)
{
       memcpy(dst, src, 8);
}


static void rawsock_destruct(struct sock *sk)
{
	pr_debug("sk=%p\n", sk);

	if (sk->sk_state == TCP_ESTABLISHED) {
		nfc_deactivate_target(nfc_rawsock(sk)->dev,
				      nfc_rawsock(sk)->target_idx);
		nfc_put_device(nfc_rawsock(sk)->dev);
	}

	skb_queue_purge(&sk->sk_receive_queue);

	if (!sock_flag(sk, SOCK_DEAD)) {
		pr_err("Freeing alive NFC raw socket %p\n", sk);
		return;
	}
}


static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr,
			    int *usockaddr_len, int peer)
{
	int len = 0;
	int error = 0;
	struct l2tp_session *session;
	struct l2tp_tunnel *tunnel;
	struct sock *sk = sock->sk;
	struct inet_sock *inet;
	struct pppol2tp_session *pls;

	error = -ENOTCONN;
	if (sk == NULL)
		goto end;
	if (sk->sk_state != PPPOX_CONNECTED)
		goto end;

	error = -EBADF;
	session = pppol2tp_sock_to_session(sk);
	if (session == NULL)
		goto end;

	pls = l2tp_session_priv(session);
	tunnel = l2tp_sock_to_tunnel(pls->tunnel_sock);
	if (tunnel == NULL) {
		error = -EBADF;
		goto end_put_sess;
	}

	inet = inet_sk(tunnel->sock);
	if ((tunnel->version == 2) && (tunnel->sock->sk_family == AF_INET)) {
		struct sockaddr_pppol2tp sp;
		len = sizeof(sp);
		memset(&sp, 0, len);
		sp.sa_family	= AF_PPPOX;
		sp.sa_protocol	= PX_PROTO_OL2TP;
		sp.pppol2tp.fd  = tunnel->fd;
		sp.pppol2tp.pid = pls->owner;
		sp.pppol2tp.s_tunnel = tunnel->tunnel_id;
		sp.pppol2tp.d_tunnel = tunnel->peer_tunnel_id;
		sp.pppol2tp.s_session = session->session_id;
		sp.pppol2tp.d_session = session->peer_session_id;
		sp.pppol2tp.addr.sin_family = AF_INET;
		sp.pppol2tp.addr.sin_port = inet->inet_dport;
		sp.pppol2tp.addr.sin_addr.s_addr = inet->inet_daddr;
		memcpy(uaddr, &sp, len);
#if IS_ENABLED(CONFIG_IPV6)
	} else if ((tunnel->version == 2) &&
		   (tunnel->sock->sk_family == AF_INET6)) {
		struct sockaddr_pppol2tpin6 sp;

		len = sizeof(sp);
		memset(&sp, 0, len);
		sp.sa_family	= AF_PPPOX;
		sp.sa_protocol	= PX_PROTO_OL2TP;
		sp.pppol2tp.fd  = tunnel->fd;
		sp.pppol2tp.pid = pls->owner;
		sp.pppol2tp.s_tunnel = tunnel->tunnel_id;
		sp.pppol2tp.d_tunnel = tunnel->peer_tunnel_id;
		sp.pppol2tp.s_session = session->session_id;
		sp.pppol2tp.d_session = session->peer_session_id;
		sp.pppol2tp.addr.sin6_family = AF_INET6;
		sp.pppol2tp.addr.sin6_port = inet->inet_dport;
		memcpy(&sp.pppol2tp.addr.sin6_addr, &tunnel->sock->sk_v6_daddr,
		       sizeof(tunnel->sock->sk_v6_daddr));
		memcpy(uaddr, &sp, len);
	} else if ((tunnel->version == 3) &&
		   (tunnel->sock->sk_family == AF_INET6)) {
		struct sockaddr_pppol2tpv3in6 sp;

		len = sizeof(sp);
		memset(&sp, 0, len);
		sp.sa_family	= AF_PPPOX;
		sp.sa_protocol	= PX_PROTO_OL2TP;
		sp.pppol2tp.fd  = tunnel->fd;
		sp.pppol2tp.pid = pls->owner;
		sp.pppol2tp.s_tunnel = tunnel->tunnel_id;
		sp.pppol2tp.d_tunnel = tunnel->peer_tunnel_id;
		sp.pppol2tp.s_session = session->session_id;
		sp.pppol2tp.d_session = session->peer_session_id;
		sp.pppol2tp.addr.sin6_family = AF_INET6;
		sp.pppol2tp.addr.sin6_port = inet->inet_dport;
		memcpy(&sp.pppol2tp.addr.sin6_addr, &tunnel->sock->sk_v6_daddr,
		       sizeof(tunnel->sock->sk_v6_daddr));
		memcpy(uaddr, &sp, len);
#endif
	} else if (tunnel->version == 3) {
		struct sockaddr_pppol2tpv3 sp;
		len = sizeof(sp);
		memset(&sp, 0, len);
		sp.sa_family	= AF_PPPOX;
		sp.sa_protocol	= PX_PROTO_OL2TP;
		sp.pppol2tp.fd  = tunnel->fd;
		sp.pppol2tp.pid = pls->owner;
		sp.pppol2tp.s_tunnel = tunnel->tunnel_id;
		sp.pppol2tp.d_tunnel = tunnel->peer_tunnel_id;
		sp.pppol2tp.s_session = session->session_id;
		sp.pppol2tp.d_session = session->peer_session_id;
		sp.pppol2tp.addr.sin_family = AF_INET;
		sp.pppol2tp.addr.sin_port = inet->inet_dport;
		sp.pppol2tp.addr.sin_addr.s_addr = inet->inet_daddr;
		memcpy(uaddr, &sp, len);
	}

	*usockaddr_len = len;

	sock_put(pls->tunnel_sock);
end_put_sess:
	sock_put(sk);
	error = 0;

end:
	return error;
}


static int __init vmci_transport_init(void)
{
	int err;

	/* Create the datagram handle that we will use to send and receive all
	 * VSocket control messages for this context.
	 */
	err = vmci_transport_datagram_create_hnd(VMCI_TRANSPORT_PACKET_RID,
						 VMCI_FLAG_ANYCID_DG_HND,
						 vmci_transport_recv_stream_cb,
						 NULL,
						 &vmci_transport_stream_handle);
	if (err < VMCI_SUCCESS) {
		pr_err("Unable to create datagram handle. (%d)\n", err);
		return vmci_transport_error_to_vsock_error(err);
	}

	err = vmci_event_subscribe(VMCI_EVENT_QP_RESUMED,
				   vmci_transport_qp_resumed_cb,
				   NULL, &vmci_transport_qp_resumed_sub_id);
	if (err < VMCI_SUCCESS) {
		pr_err("Unable to subscribe to resumed event. (%d)\n", err);
		err = vmci_transport_error_to_vsock_error(err);
		vmci_transport_qp_resumed_sub_id = VMCI_INVALID_ID;
		goto err_destroy_stream_handle;
	}

	err = vsock_core_init(&vmci_transport);
	if (err < 0)
		goto err_unsubscribe;

	return 0;

err_unsubscribe:
	vmci_event_unsubscribe(vmci_transport_qp_resumed_sub_id);
err_destroy_stream_handle:
	vmci_datagram_destroy_handle(vmci_transport_stream_handle);
	return err;
}


void iucv_sock_link(struct iucv_sock_list *l, struct sock *sk)
{
	write_lock_bh(&l->lock);
	sk_add_node(sk, &l->head);
	write_unlock_bh(&l->lock);
}


static int afiucv_hs_callback_fin(struct sock *sk, struct sk_buff *skb)
{
	struct iucv_sock *iucv = iucv_sk(sk);

	/* other end of connection closed */
	if (!iucv)
		goto out;
	bh_lock_sock(sk);
	if (sk->sk_state == IUCV_CONNECTED) {
		sk->sk_state = IUCV_DISCONN;
		sk->sk_state_change(sk);
	}
	bh_unlock_sock(sk);
out:
	kfree_skb(skb);
	return NET_RX_SUCCESS;
}


static void power_pmu_enable(struct pmu *pmu)
{
	struct perf_event *event;
	struct cpu_hw_events *cpuhw;
	unsigned long flags;
	long i;
	unsigned long val;
	s64 left;
	unsigned int hwc_index[MAX_HWEVENTS];
	int n_lim;
	int idx;

	if (!ppmu)
		return;
	local_irq_save(flags);
	cpuhw = &__get_cpu_var(cpu_hw_events);
	if (!cpuhw->disabled) {
		local_irq_restore(flags);
		return;
	}
	cpuhw->disabled = 0;

	/*
	 * If we didn't change anything, or only removed events,
	 * no need to recalculate MMCR* settings and reset the PMCs.
	 * Just reenable the PMU with the current MMCR* settings
	 * (possibly updated for removal of events).
	 */
	if (!cpuhw->n_added) {
		mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE);
		mtspr(SPRN_MMCR1, cpuhw->mmcr[1]);
		if (cpuhw->n_events == 0)
			ppc_set_pmu_inuse(0);
		goto out_enable;
	}

	/*
	 * Compute MMCR* values for the new set of events
	 */
	if (ppmu->compute_mmcr(cpuhw->events, cpuhw->n_events, hwc_index,
			       cpuhw->mmcr)) {
		/* shouldn't ever get here */
		printk(KERN_ERR "oops compute_mmcr failed\n");
		goto out;
	}

	/*
	 * Add in MMCR0 freeze bits corresponding to the
	 * attr.exclude_* bits for the first event.
	 * We have already checked that all events have the
	 * same values for these bits as the first event.
	 */
	event = cpuhw->event[0];
	if (event->attr.exclude_user)
		cpuhw->mmcr[0] |= MMCR0_FCP;
	if (event->attr.exclude_kernel)
		cpuhw->mmcr[0] |= freeze_events_kernel;
	if (event->attr.exclude_hv)
		cpuhw->mmcr[0] |= MMCR0_FCHV;

	/*
	 * Write the new configuration to MMCR* with the freeze
	 * bit set and set the hardware events to their initial values.
	 * Then unfreeze the events.
	 */
	ppc_set_pmu_inuse(1);
	mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE);
	mtspr(SPRN_MMCR1, cpuhw->mmcr[1]);
	mtspr(SPRN_MMCR0, (cpuhw->mmcr[0] & ~(MMCR0_PMC1CE | MMCR0_PMCjCE))
				| MMCR0_FC);

	/*
	 * Read off any pre-existing events that need to move
	 * to another PMC.
	 */
	for (i = 0; i < cpuhw->n_events; ++i) {
		event = cpuhw->event[i];
		if (event->hw.idx && event->hw.idx != hwc_index[i] + 1) {
			power_pmu_read(event);
			write_pmc(event->hw.idx, 0);
			event->hw.idx = 0;
		}
	}

	/*
	 * Initialize the PMCs for all the new and moved events.
	 */
	cpuhw->n_limited = n_lim = 0;
	for (i = 0; i < cpuhw->n_events; ++i) {
		event = cpuhw->event[i];
		if (event->hw.idx)
			continue;
		idx = hwc_index[i] + 1;
		if (is_limited_pmc(idx)) {
			cpuhw->limited_counter[n_lim] = event;
			cpuhw->limited_hwidx[n_lim] = idx;
			++n_lim;
			continue;
		}
		val = 0;
		if (event->hw.sample_period) {
			left = local64_read(&event->hw.period_left);
			if (left < 0x80000000L)
				val = 0x80000000L - left;
		}
		local64_set(&event->hw.prev_count, val);
		event->hw.idx = idx;
		if (event->hw.state & PERF_HES_STOPPED)
			val = 0;
		write_pmc(idx, val);
		perf_event_update_userpage(event);
	}
	cpuhw->n_limited = n_lim;
	cpuhw->mmcr[0] |= MMCR0_PMXE | MMCR0_FCECE;

 out_enable:
	mb();
	write_mmcr0(cpuhw, cpuhw->mmcr[0]);

	/*
	 * Enable instruction sampling if necessary
	 */
	if (cpuhw->mmcr[2] & MMCRA_SAMPLE_ENABLE) {
		mb();
		mtspr(SPRN_MMCRA, cpuhw->mmcr[2]);
	}

 out:
	local_irq_restore(flags);
}


TFE_TensorHandle* TFE_HandleFromDLPack(void* dlm, TF_Status* status,
                                       TFE_Context* ctx) {
  DLManagedTensor* dlmt = static_cast<DLManagedTensor*>(dlm);
  DLTensor* dl_tensor = &dlmt->dl_tensor;
  absl::optional<std::string> device_name =
      DeviceNameFromDlContext(dl_tensor->ctx, status);
  if (!device_name.has_value()) {
    status->status =
        tensorflow::errors::InvalidArgument("Unsupported Device Type");
    return nullptr;
  }
  TF_DataType dtype;
  Status s = TfDataTypeFormDlDataType(dl_tensor->dtype, &dtype);
  if (!s.ok()) {
    status->status = std::move(s);
    return nullptr;
  }
  int num_dims = dl_tensor->ndim;
  const int64_t* dims = dl_tensor->shape;
  void* data = dl_tensor->data;

  size_t total_bytes = dl_tensor->dtype.bits / 8;
  for (int i = 0; i < num_dims; i++) {
    total_bytes *= dims[i];
  }

  if (dl_tensor->strides != nullptr &&
      !IsValidStrideCompactRowMajorData(dl_tensor->shape, dl_tensor->strides,
                                        num_dims)) {
    status->status = tensorflow::errors::InvalidArgument(
        "Invalid strides array from DLPack");
    return nullptr;
  }

  TFE_TensorHandle* handle = TFE_NewTensorHandleFromDeviceMemory(
      ctx, device_name.value().c_str(), dtype, dims, num_dims, data,
      total_bytes, &DeallocatorWrapperFunc, dlmt, status);

  return handle;
}


  py::handle get_op_callbacks() const {
    return GetPyObject(&GetData()->op_callbacks);
  }


PyObject* OutputTFE_Context(TFE_Context* context) {
  return PyCapsule_New(context, nullptr, TFE_DeleteContextCapsule);
}


AP4_AvccAtom::AP4_AvccAtom(const AP4_AvccAtom& other) :
    AP4_Atom(AP4_ATOM_TYPE_AVCC, other.m_Size32),
    m_ConfigurationVersion(other.m_ConfigurationVersion),
    m_Profile(other.m_Profile),
    m_Level(other.m_Level),
    m_ProfileCompatibility(other.m_ProfileCompatibility),
    m_NaluLengthSize(other.m_NaluLengthSize),
    m_RawBytes(other.m_RawBytes)
{
    // deep copy of the parameters
    unsigned int i = 0;
    for (i=0; i<other.m_SequenceParameters.ItemCount(); i++) {
        m_SequenceParameters.Append(other.m_SequenceParameters[i]);
    }
    for (i=0; i<other.m_PictureParameters.ItemCount(); i++) {
        m_PictureParameters.Append(other.m_PictureParameters[i]);
    }
}


AP4_HvccAtom::AP4_HvccAtom(AP4_UI32 size, const AP4_UI08* payload) :
    AP4_Atom(AP4_ATOM_TYPE_HVCC, size)
{
    // make a copy of our configuration bytes
    unsigned int payload_size = size-AP4_ATOM_HEADER_SIZE;

    // keep a raw copy
    if (payload_size < 22) return;
    m_RawBytes.SetData(payload, payload_size);

    // parse the payload
    m_ConfigurationVersion   = payload[0];
    m_GeneralProfileSpace    = (payload[1]>>6) & 0x03;
    m_GeneralTierFlag        = (payload[1]>>5) & 0x01;
    m_GeneralProfile         = (payload[1]   ) & 0x1F;
    m_GeneralProfileCompatibilityFlags = AP4_BytesToUInt32BE(&payload[2]);
    m_GeneralConstraintIndicatorFlags  = (((AP4_UI64)AP4_BytesToUInt32BE(&payload[6]))<<16) | AP4_BytesToUInt16BE(&payload[10]);
    m_GeneralLevel           = payload[12];
    m_Reserved1              = (payload[13]>>4) & 0x0F;
    m_MinSpatialSegmentation = AP4_BytesToUInt16BE(&payload[13]) & 0x0FFF;
    m_Reserved2              = (payload[15]>>2) & 0x3F;
    m_ParallelismType        = payload[15] & 0x03;
    m_Reserved3              = (payload[16]>>2) & 0x3F;
    m_ChromaFormat           = payload[16] & 0x03;
    m_Reserved4              = (payload[17]>>3) & 0x1F;
    m_LumaBitDepth           = 8+(payload[17] & 0x07);
    m_Reserved5              = (payload[18]>>3) & 0x1F;
    m_ChromaBitDepth         = 8+(payload[18] & 0x07);
    m_AverageFrameRate       = AP4_BytesToUInt16BE(&payload[19]);
    m_ConstantFrameRate      = (payload[21]>>6) & 0x03;
    m_NumTemporalLayers      = (payload[21]>>3) & 0x07;
    m_TemporalIdNested       = (payload[21]>>2) & 0x01;
    m_NaluLengthSize         = 1+(payload[21] & 0x03);

    AP4_UI08 num_seq = payload[22];
    m_Sequences.SetItemCount(num_seq);
    unsigned int cursor = 23;
    for (unsigned int i=0; i<num_seq; i++) {

        Sequence& seq = m_Sequences[i];
        if (cursor+1 > payload_size) break;
        seq.m_ArrayCompleteness = (payload[cursor] >> 7) & 0x01;
        seq.m_Reserved          = (payload[cursor] >> 6) & 0x01;
        seq.m_NaluType          = payload[cursor] & 0x3F;
        cursor += 1;

        if (cursor+2 > payload_size) break;
        AP4_UI16 nalu_count = AP4_BytesToUInt16BE(&payload[cursor]);
        seq.m_Nalus.SetItemCount(nalu_count);
        cursor += 2;

        for (unsigned int j=0; j<nalu_count; j++) {
            if (cursor+2 > payload_size) break;
            unsigned int nalu_length = AP4_BytesToUInt16BE(&payload[cursor]);
            cursor += 2;
            if (cursor + nalu_length > payload_size) break;
            seq.m_Nalus[j].SetData(&payload[cursor], nalu_length);
            cursor += nalu_length;
        }
    }
}


PHP_METHOD(HttpParams, __construct)
{
	zval *zcopy, *zparams = NULL, *param_sep = NULL, *arg_sep = NULL, *val_sep = NULL;
	long flags = PHP_HTTP_PARAMS_DEFAULT;
	zend_error_handling zeh;

	php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!/z/z/z/l", &zparams, &param_sep, &arg_sep, &val_sep, &flags), invalid_arg, return);

	zend_replace_error_handling(EH_THROW, php_http_exception_runtime_class_entry, &zeh TSRMLS_CC);
	{
		switch (ZEND_NUM_ARGS()) {
			case 5:
				zend_update_property_long(php_http_params_class_entry, getThis(), ZEND_STRL("flags"), flags TSRMLS_CC);
				/* no break */
			case 4:
				zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), val_sep TSRMLS_CC);
				/* no break */
			case 3:
				zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), arg_sep TSRMLS_CC);
				/* no break */
			case 2:
				zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), param_sep TSRMLS_CC);
				/* no break */
		}

		if (zparams) {
			switch (Z_TYPE_P(zparams)) {
				case IS_OBJECT:
				case IS_ARRAY:
					zcopy = php_http_zsep(1, IS_ARRAY, zparams);
					zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), zcopy TSRMLS_CC);
					zval_ptr_dtor(&zcopy);
					break;
				default:
					zcopy = php_http_ztyp(IS_STRING, zparams);
					if (Z_STRLEN_P(zcopy)) {
						php_http_params_opts_t opts = {
							{Z_STRVAL_P(zcopy), Z_STRLEN_P(zcopy)},
							php_http_params_separator_init(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("param_sep"), 0 TSRMLS_CC) TSRMLS_CC),
							php_http_params_separator_init(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("arg_sep"), 0 TSRMLS_CC) TSRMLS_CC),
							php_http_params_separator_init(zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("val_sep"), 0 TSRMLS_CC) TSRMLS_CC),
							NULL, flags
						};

						MAKE_STD_ZVAL(zparams);
						array_init(zparams);
						php_http_params_parse(Z_ARRVAL_P(zparams), &opts TSRMLS_CC);
						zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), zparams TSRMLS_CC);
						zval_ptr_dtor(&zparams);

						php_http_params_separator_free(opts.param);
						php_http_params_separator_free(opts.arg);
						php_http_params_separator_free(opts.val);
					}
					zval_ptr_dtor(&zcopy);
					break;
			}
		} else {
			MAKE_STD_ZVAL(zparams);
			array_init(zparams);
			zend_update_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), zparams TSRMLS_CC);
			zval_ptr_dtor(&zparams);
		}
	}
	zend_restore_error_handling(&zeh TSRMLS_CC);
}


php_http_buffer_t *php_http_params_to_string(php_http_buffer_t *buf, HashTable *params, const char *pss, size_t psl, const char *ass, size_t asl, const char *vss, size_t vsl, unsigned flags TSRMLS_DC)
{
	zval **zparam;
	HashPosition pos, pos1;
	php_http_array_hashkey_t key = php_http_array_hashkey_init(0), key1 = php_http_array_hashkey_init(0);
	zend_bool rfc5987 = 0;

	if (!buf) {
		buf = php_http_buffer_init(NULL);
	}

	FOREACH_HASH_KEYVAL(pos, params, key, zparam) {
		zval **zvalue, **zargs;

		if (Z_TYPE_PP(zparam) != IS_ARRAY) {
			zvalue = zparam;
		} else {
			if (SUCCESS != zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("value"), (void *) &zvalue)) {
				if (SUCCESS != zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("*rfc5987*"), (void *) &zvalue)) {
					zvalue = zparam;
				} else {
					rfc5987 = 1;
				}
			}
		}

		php_http_array_hashkey_stringify(&key);
		shift_param(buf, key.str, key.len - 1, *zvalue, pss, psl, ass, asl, vss, vsl, flags, rfc5987 TSRMLS_CC);
		php_http_array_hashkey_stringfree(&key);

		if (Z_TYPE_PP(zparam) == IS_ARRAY && SUCCESS != zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("arguments"), (void *) &zvalue)) {
			if (zvalue == zparam) {
				continue;
			}
			zvalue = zparam;
		}

		if (Z_TYPE_PP(zvalue) == IS_ARRAY) {
			FOREACH_KEYVAL(pos1, *zvalue, key1, zargs) {
				if (zvalue == zparam && key1.type == HASH_KEY_IS_STRING && !strcmp(key1.str, "value")) {
					continue;
				}

				php_http_array_hashkey_stringify(&key1);
				shift_arg(buf, key1.str, key1.len - 1, *zargs, ass, asl, vss, vsl, flags TSRMLS_CC);
				php_http_array_hashkey_stringfree(&key1);
			}
		}
	}

	php_http_buffer_shrink(buf);
	php_http_buffer_fix(buf);

	return buf;
}


static void merge_param(HashTable *params, zval *zdata, zval ***current_param, zval ***current_args TSRMLS_DC)
{
	zval **ptr, **zdata_ptr;
	php_http_array_hashkey_t hkey = php_http_array_hashkey_init(0);

#if 0
	{
		zval tmp;
		INIT_PZVAL_ARRAY(&tmp, params);
		fprintf(stderr, "params = ");
		zend_print_zval_r(&tmp, 1 TSRMLS_CC);
		fprintf(stderr, "\n");
	}
#endif

	hkey.type = zend_hash_get_current_key_ex(Z_ARRVAL_P(zdata), &hkey.str, &hkey.len, &hkey.num, hkey.dup, NULL);

	if ((hkey.type == HASH_KEY_IS_STRING && !zend_hash_exists(params, hkey.str, hkey.len))
	||	(hkey.type == HASH_KEY_IS_LONG && !zend_hash_index_exists(params, hkey.num))
	) {
		zval *tmp, *arg, **args;

		/* create the entry if it doesn't exist */
		zend_hash_get_current_data(Z_ARRVAL_P(zdata), (void *) &ptr);
		Z_ADDREF_PP(ptr);
		MAKE_STD_ZVAL(tmp);
		array_init(tmp);
		add_assoc_zval_ex(tmp, ZEND_STRS("value"), *ptr);

		MAKE_STD_ZVAL(arg);
		array_init(arg);
		zend_hash_update(Z_ARRVAL_P(tmp), "arguments", sizeof("arguments"), (void *) &arg, sizeof(zval *), (void *) &args);
		*current_args = args;

		if (hkey.type == HASH_KEY_IS_STRING) {
			zend_hash_update(params, hkey.str, hkey.len, (void *) &tmp, sizeof(zval *), (void *) &ptr);
		} else {
			zend_hash_index_update(params, hkey.num, (void *) &tmp, sizeof(zval *), (void *) &ptr);
		}
	} else {
		/* merge */
		if (hkey.type == HASH_KEY_IS_STRING) {
			zend_hash_find(params, hkey.str, hkey.len, (void *) &ptr);
		} else {
			zend_hash_index_find(params, hkey.num, (void *) &ptr);
		}

		zdata_ptr = &zdata;

		if (Z_TYPE_PP(ptr) == IS_ARRAY
		&&	SUCCESS == zend_hash_find(Z_ARRVAL_PP(ptr), "value", sizeof("value"), (void *) &ptr)
		&&	SUCCESS == zend_hash_get_current_data(Z_ARRVAL_PP(zdata_ptr), (void *) &zdata_ptr)
		) {
			/*
			 * params = [arr => [value => [0 => 1]]]
			 *                            ^- ptr
			 * zdata  = [arr => [0 => NULL]]
			 *                  ^- zdata_ptr
			 */
			zval **test_ptr;

			while (Z_TYPE_PP(zdata_ptr) == IS_ARRAY
			&&	SUCCESS == zend_hash_get_current_data(Z_ARRVAL_PP(zdata_ptr), (void *) &test_ptr)
			) {
				if (Z_TYPE_PP(test_ptr) == IS_ARRAY && Z_TYPE_PP(ptr) == IS_ARRAY) {

					/* now find key in ptr */
					if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_PP(zdata_ptr), &hkey.str, &hkey.len, &hkey.num, hkey.dup, NULL)) {
						if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(ptr), hkey.str, hkey.len, (void *) &ptr)) {
							zdata_ptr = test_ptr;
						} else {
							Z_ADDREF_PP(test_ptr);
							zend_hash_update(Z_ARRVAL_PP(ptr), hkey.str, hkey.len, (void *) test_ptr, sizeof(zval *), (void *) &ptr);
							break;
						}
					} else {
						if (SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(ptr), hkey.num, (void *) &ptr)) {
							zdata_ptr = test_ptr;
						} else if (hkey.num) {
							Z_ADDREF_PP(test_ptr);
							zend_hash_index_update(Z_ARRVAL_PP(ptr), hkey.num, (void *) test_ptr, sizeof(zval *), (void *) &ptr);
							break;
						} else {
							Z_ADDREF_PP(test_ptr);
							zend_hash_next_index_insert(Z_ARRVAL_PP(ptr), (void *) test_ptr, sizeof(zval *), (void *) &ptr);
							break;
						}
					}
				} else {
					/* this is the leaf */
					Z_ADDREF_PP(test_ptr);
					if (Z_TYPE_PP(ptr) != IS_ARRAY) {
						zval_dtor(*ptr);
						array_init(*ptr);
					}
					if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(Z_ARRVAL_PP(zdata_ptr), &hkey.str, &hkey.len, &hkey.num, hkey.dup, NULL)) {
						zend_hash_update(Z_ARRVAL_PP(ptr), hkey.str, hkey.len, (void *) test_ptr, sizeof(zval *), (void *) &ptr);
					} else if (hkey.num) {
						zend_hash_index_update(Z_ARRVAL_PP(ptr), hkey.num, (void *) test_ptr, sizeof(zval *), (void *) &ptr);
					} else {
						zend_hash_next_index_insert(Z_ARRVAL_PP(ptr), (void *) test_ptr, sizeof(zval *), (void *) &ptr);
					}
					break;
				}
			}

		}
	}

	/* bubble up */
	while (Z_TYPE_PP(ptr) == IS_ARRAY && SUCCESS == zend_hash_get_current_data(Z_ARRVAL_PP(ptr), (void *) &ptr));
	*current_param = ptr;
}


static inline void sanitize_rfc5988(char *str, size_t len, zval *zv TSRMLS_DC)
{
	zval_dtor(zv);
	php_trim(str, len, " ><", 3, zv, 3 TSRMLS_CC);
}


PHP_METHOD(HttpParams, offsetGet)
{
	char *name_str;
	int name_len;
	zval **zparam, *zparams;

	if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len)) {
		return;
	}

	zparams = php_http_ztyp(IS_ARRAY, zend_read_property(php_http_params_class_entry, getThis(), ZEND_STRL("params"), 0 TSRMLS_CC));

	if (SUCCESS == zend_symtable_find(Z_ARRVAL_P(zparams), name_str, name_len + 1, (void *) &zparam)) {
		RETVAL_ZVAL(*zparam, 1, 0);
	}

	zval_ptr_dtor(&zparams);
}


int wav_parse(wav_reader_t *reader, int64_t *data_length)
{
    uint32_t container, fcc, chunk_size;
    int fmt_seen = 0;

    *data_length = 0;
    container = riff_next_chunk(reader, &chunk_size);
    ENSURE(container == RIFF_FOURCC('R','I','F','F') ||
           container == RIFF_FOURCC('R','F','6','4'));
    TRY_IO(pcm_read32le(&reader->io, &fcc));
    ENSURE(fcc == RIFF_FOURCC('W','A','V','E'));

    if (container == RIFF_FOURCC('R','F','6','4'))
        riff_ds64(reader, data_length);
    while ((fcc = riff_next_chunk(reader, &chunk_size)) != 0) {
        if (fcc == RIFF_FOURCC('f','m','t',' ')) {
            fmt_seen = 1;
            if (wav_fmt(reader, chunk_size) < 0)
                goto FAIL;
        } else if (fcc == RIFF_FOURCC('d','a','t','a')) {
            if (container == RIFF_FOURCC('R','I','F','F'))
                *data_length = chunk_size;
            reader->data_offset = pcm_tell(&reader->io);
            break;
        } else {
            TRY_IO(pcm_skip(&reader->io, (chunk_size + 1) & ~1));
        }
    }
    ENSURE(fmt_seen && fcc == RIFF_FOURCC('d', 'a', 't', 'a'));
    return 0;
FAIL:
    return -1;
}


    void AddReference() {
        ++m_ReferenceCount;
    }


MakeAudioSetupData(AP4_DataBuffer&        audio_setup_data,
                   AP4_SampleDescription* sample_description,
                   AP4_DataBuffer&        sample_data /* needed for encrypted AC3 */)
{
    AP4_UI08       audio_type[4];
    AP4_DataBuffer setup_data;

    if (sample_description->GetFormat() == AP4_SAMPLE_FORMAT_MP4A) {
        AP4_MpegAudioSampleDescription* mpeg_audio_desc = AP4_DYNAMIC_CAST(AP4_MpegAudioSampleDescription, sample_description);
        if (mpeg_audio_desc == NULL ||
            !(mpeg_audio_desc->GetObjectTypeId() == AP4_OTI_MPEG4_AUDIO          ||
              mpeg_audio_desc->GetObjectTypeId() == AP4_OTI_MPEG2_AAC_AUDIO_LC   ||
              mpeg_audio_desc->GetObjectTypeId() == AP4_OTI_MPEG2_AAC_AUDIO_MAIN)) {
            return AP4_ERROR_NOT_SUPPORTED;
        }
        const AP4_DataBuffer& dsi = mpeg_audio_desc->GetDecoderInfo();
        setup_data.SetData(dsi.GetData(), dsi.GetDataSize());

        AP4_Mp4AudioDecoderConfig dec_config;
        AP4_Result result = dec_config.Parse(dsi.GetData(), dsi.GetDataSize());
        if (AP4_FAILED(result)) {
            return AP4_ERROR_INVALID_FORMAT;
        }

        if (dec_config.m_Extension.m_SbrPresent || dec_config.m_Extension.m_PsPresent) {
            if (dec_config.m_Extension.m_PsPresent) {
                audio_type[0] = 'z';
                audio_type[1] = 'a';
                audio_type[2] = 'c';
                audio_type[3] = 'p';
            } else {
                audio_type[0] = 'z';
                audio_type[1] = 'a';
                audio_type[2] = 'c';
                audio_type[3] = 'h';
            }
        } else {
            audio_type[0] = 'z';
            audio_type[1] = 'a';
            audio_type[2] = 'a';
            audio_type[3] = 'c';
        }
    } else if (sample_description->GetFormat() == AP4_SAMPLE_FORMAT_AC_3) {
        audio_type[0] = 'z';
        audio_type[1] = 'a';
        audio_type[2] = 'c';
        audio_type[3] = '3';

        // the setup data is the first 10 bytes of a syncframe
        if (sample_data.GetDataSize() >= 10) {
            setup_data.SetData(sample_data.GetData(), 10);
        }
    } else if (sample_description->GetFormat() == AP4_SAMPLE_FORMAT_EC_3) {
        audio_type[0] = 'z';
        audio_type[1] = 'e';
        audio_type[2] = 'c';
        audio_type[3] = '3';

        AP4_Dec3Atom* dec3 = AP4_DYNAMIC_CAST(AP4_Dec3Atom, sample_description->GetDetails().GetChild(AP4_ATOM_TYPE_DEC3));
        if (dec3 == NULL) {
            fprintf(stderr, "ERROR: failed to find 'dec3' atom in sample description\n");
            return 1;
        }
        setup_data.SetData(dec3->GetRawBytes().GetData(), dec3->GetRawBytes().GetDataSize());
    } else {
        return AP4_SUCCESS;
    }

    audio_setup_data.SetDataSize(8+setup_data.GetDataSize());
    AP4_UI08* payload = audio_setup_data.UseData();
    payload[0] = audio_type[0];
    payload[1] = audio_type[1];
    payload[2] = audio_type[2];
    payload[3] = audio_type[3];
    payload[4] = 0; // priming
    payload[5] = 0; // priming
    payload[6] = 1; // version
    payload[7] = setup_data.GetDataSize(); // setup_data_length
    if (setup_data.GetDataSize()) {
        AP4_CopyMemory(&payload[8], setup_data.GetData(), setup_data.GetDataSize());
    }

    return AP4_SUCCESS;
}


GF_Err gf_hevc_get_sps_info(u8 *sps_data, u32 sps_size, u32 *sps_id, u32 *width, u32 *height, s32 *par_n, s32 *par_d)
{
	HEVCState hevc;
	memset(&hevc, 0, sizeof(HEVCState));
	hevc.sps_active_idx = -1;
	return gf_hevc_get_sps_info_with_state(&hevc, sps_data, sps_size, sps_id, width, height, par_n, par_d);
}


static void vp9_segmentation_params(GF_BitStream *bs)
{
	Bool segmentation_enabled = gf_bs_read_int_log(bs, 1, "segmentation_enabled");
	if (segmentation_enabled == 1) {
		int i;
		Bool segmentation_update_map = gf_bs_read_int_log(bs, 1, "segmentation_update_map");
		if (segmentation_update_map) {
			for (i = 0; i < 7; i++)
				/*segmentation_tree_probs[i] = read_prob()*/
				/*segmentation_temporal_update = */gf_bs_read_int_log(bs, 1, "segmentation_temporal_update");
			/*for (i = 0; i < 3; i++)
				segmentation_pred_prob[i] = segmentation_temporal_update ? read_prob() : 255*/
		}
		Bool segmentation_update_data = gf_bs_read_int_log(bs, 1, "segmentation_update_data");
		if (segmentation_update_data == 1) {
			/*segmentation_abs_or_delta_update =*/ gf_bs_read_int_log(bs, 1, "segmentation_abs_or_delta_update");
			for (i = 0; i < VP9_MAX_SEGMENTS; i++) {
				int j;
				for (j = 0; j < VP9_SEG_LVL_MAX; j++) {
					/*feature_value = 0*/
					Bool feature_enabled = gf_bs_read_int_log(bs, 1, "feature_enabled");
					/*FeatureEnabled[i][j] = feature_enabled*/
					if (feature_enabled) {
						int bits_to_read = segmentation_feature_bits[j];
						/*feature_value =*/ gf_bs_read_int_log(bs, bits_to_read, "feature_value");
						if (segmentation_feature_signed[j] == 1) {
							/*Bool feature_sign = */gf_bs_read_int_log(bs, 1, "feature_sign");
							/*if (feature_sign == 1)
								feature_value *= -1*/
						}
					}
					/*FeatureData[i][j] = feature_value*/
				}
			}
		}
	}
}


static void av1_parse_uncompressed_header(GF_BitStream *bs, AV1State *state)
{
	Bool error_resilient_mode = GF_FALSE, allow_screen_content_tools = GF_FALSE, force_integer_mv = GF_FALSE;
	Bool /*use_ref_frame_mvs = GF_FALSE,*/ FrameIsIntra = GF_FALSE, frame_size_override_flag = GF_FALSE;
	Bool disable_cdf_update = GF_FALSE;
	u8 showable_frame;
	u8 primary_ref_frame;
	u16 idLen = 0;
	u32 idx;
	s8 ref_frame_idx[AV1_REFS_PER_FRAME];
	AV1StateFrame *frame_state = &state->frame_state;

	if (state->frame_id_numbers_present_flag) {
		idLen = (state->additional_frame_id_length_minus_1 + state->delta_frame_id_length_minus_2 + 3);
	}
	frame_state->refresh_frame_flags = 0;

	showable_frame = 0;
	if (state->reduced_still_picture_header) {
		frame_state->key_frame = GF_TRUE;
		FrameIsIntra = GF_TRUE;
		frame_state->frame_type = AV1_KEY_FRAME;
		frame_state->show_frame = GF_TRUE;
		frame_state->show_existing_frame = 0;
	}
	else {
		frame_state->show_existing_frame = gf_bs_read_int_log(bs, 1, "show_existing_frame");
		if (frame_state->show_existing_frame == GF_TRUE) {
			frame_state->frame_to_show_map_idx = gf_bs_read_int_log(bs, 3, "frame_to_show_map_idx");
			frame_state->frame_type = state->RefFrameType[frame_state->frame_to_show_map_idx];

			if (state->decoder_model_info_present_flag && !state->equal_picture_interval) {
				gf_bs_read_int_log(bs, state->frame_presentation_time_length, "frame_presentation_time");
			}

			frame_state->refresh_frame_flags = 0;
			if (state->frame_id_numbers_present_flag) {
				gf_bs_read_int_log(bs, idLen, "display_frame_id");
			}
			if (frame_state->frame_type == AV1_KEY_FRAME) {
				frame_state->refresh_frame_flags = AV1_ALL_FRAMES;
			}
			/*
			if (film_grain_params_present) {
				load_grain_params(frame_to_show_map_idx)
			}*/
			return;
		}
		frame_state->frame_type = gf_bs_read_int_log(bs, 2, "frame_type");
		FrameIsIntra = (frame_state->frame_type == AV1_INTRA_ONLY_FRAME || frame_state->frame_type == AV1_KEY_FRAME);
		frame_state->show_frame = gf_bs_read_int_log(bs, 1, "show_frame");
		if (frame_state->is_first_frame) {
			frame_state->key_frame = frame_state->seen_seq_header && frame_state->show_frame && frame_state->frame_type == AV1_KEY_FRAME && frame_state->seen_frame_header;
		}
		if (frame_state->show_frame && state->decoder_model_info_present_flag && !state->equal_picture_interval) {
			gf_bs_read_int_log(bs, state->frame_presentation_time_length, "frame_presentation_time");
		}
		if (frame_state->show_frame) {
			showable_frame = frame_state->frame_type != AV1_KEY_FRAME;

		}
		else {
			showable_frame = gf_bs_read_int_log(bs, 1, "showable_frame");
		}
		if (frame_state->frame_type == AV1_SWITCH_FRAME || (frame_state->frame_type == AV1_KEY_FRAME && frame_state->show_frame))
			error_resilient_mode = GF_TRUE;
		else
			error_resilient_mode = gf_bs_read_int_log(bs, 1, "error_resilient_mode");
	}

	if ((frame_state->frame_type == AV1_KEY_FRAME) && frame_state->show_frame) {
		u32 i;
		for (i = 0; i < AV1_NUM_REF_FRAMES; i++) {
			state->RefValid[i] = 0;
			state->RefOrderHint[i] = 0;
		}
		for (i = 0; i < AV1_REFS_PER_FRAME; i++) {
			state->OrderHints[AV1_LAST_FRAME + i] = 0;
		}
	}

	disable_cdf_update = gf_bs_read_int_log(bs, 1, "disable_cdf_update");
	if (state->seq_force_screen_content_tools == 2/*SELECT_SCREEN_CONTENT_TOOLS*/) {
		allow_screen_content_tools = gf_bs_read_int_log(bs, 1, "allow_screen_content_tools");
	}
	else {
		allow_screen_content_tools = state->seq_force_screen_content_tools;
	}
	if (allow_screen_content_tools) {
		if (state->seq_force_integer_mv == 2/*SELECT_INTEGER_MV*/) {
			force_integer_mv = gf_bs_read_int_log(bs, 1, "force_integer_mv");
		}
		else {
			force_integer_mv = state->seq_force_integer_mv;
		}
	}
	else {
		force_integer_mv = 0;
	}
	if (FrameIsIntra) {
		force_integer_mv = 1;
	}
	if (state->frame_id_numbers_present_flag) {
		gf_bs_read_int_log(bs, idLen, "current_frame_id");
	}
	if (frame_state->frame_type == AV1_SWITCH_FRAME)
		frame_size_override_flag = GF_TRUE;
	else if (state->reduced_still_picture_header)
		frame_size_override_flag = GF_FALSE;
	else
		frame_size_override_flag = gf_bs_read_int_log(bs, 1, "frame_size_override_flag");

	frame_state->order_hint = gf_bs_read_int(bs, state->OrderHintBits);
	if (FrameIsIntra || error_resilient_mode) {
		primary_ref_frame = AV1_PRIMARY_REF_NONE;
	}
	else {
		primary_ref_frame = gf_bs_read_int_log(bs, 3, "primary_ref_frame");
	}

	if (state->decoder_model_info_present_flag) {
		u8 buffer_removal_time_present_flag = gf_bs_read_int_log(bs, 1, "buffer_removal_time_present_flag");
		if (buffer_removal_time_present_flag) {
			u32 opNum;
			for (opNum = 0; opNum < state->operating_points_count; opNum++) {
				if (state->decoder_model_present_for_this_op[opNum]) {
					u8 opPtIdc = state->operating_point_idc[opNum];
					u8 inTemporalLayer = (opPtIdc >> state->temporal_id) & 1;
					u8 inSpatialLayer = (opPtIdc >> (state->spatial_id + 8)) & 1;
					if (opPtIdc == 0 || (inTemporalLayer && inSpatialLayer)) {
						gf_bs_read_int_log_idx(bs, state->buffer_removal_time_length, "buffer_removal_time", opNum);
					}
				}
			}
		}
	}

	if (frame_state->frame_type == AV1_SWITCH_FRAME || (frame_state->frame_type == AV1_KEY_FRAME && frame_state->show_frame)) {
		frame_state->refresh_frame_flags = AV1_ALL_FRAMES;
	}
	else {
		frame_state->refresh_frame_flags = gf_bs_read_int_log(bs, 8, "refresh_frame_flags");
	}
	if (!FrameIsIntra || frame_state->refresh_frame_flags != AV1_ALL_FRAMES) {
		if (error_resilient_mode && state->enable_order_hint) {
			u32 i = 0;
			for (i = 0; i < AV1_NUM_REF_FRAMES; i++) {
				u8 ref_order_hint = gf_bs_read_int_log_idx(bs, state->OrderHintBits, "ref_order_hint", i);
				if (ref_order_hint != state->RefOrderHint[i]) {
					state->RefValid[i] = 0;
				}
				state->RefOrderHint[i] = ref_order_hint;
			}
		}
	}

	u8 allow_intrabc = 0;
	if (frame_state->frame_type == AV1_KEY_FRAME) {
		av1_frame_size(bs, state, frame_size_override_flag);
		av1_render_size(bs);
		if (allow_screen_content_tools && state->UpscaledWidth == state->width) {
			allow_intrabc = gf_bs_read_int_log(bs, 1, "allow_intrabc");
		}
	}
	else {
		if (frame_state->frame_type == AV1_INTRA_ONLY_FRAME) {
			av1_frame_size(bs, state, frame_size_override_flag);
			av1_render_size(bs);
			if (allow_screen_content_tools && state->UpscaledWidth == state->width) {
				allow_intrabc = gf_bs_read_int_log(bs, 1, "allow_intrabc");
			}
		}
		else {
			u32 i = 0;
			Bool frame_refs_short_signaling = GF_FALSE;
			if (state->enable_order_hint) {
				frame_refs_short_signaling = gf_bs_read_int_log(bs, 1, "frame_refs_short_signaling");
				if (frame_refs_short_signaling) {
					u8 last_frame_idx = gf_bs_read_int_log(bs, 3, "last_frame_idx");
					u8 gold_frame_idx = gf_bs_read_int_log(bs, 3, "gold_frame_idx");
					av1_set_frame_refs(state, last_frame_idx, gold_frame_idx, ref_frame_idx);
				}
			}
			for (i = 0; i < AV1_REFS_PER_FRAME; i++) {
				if (!frame_refs_short_signaling)
					ref_frame_idx[i] = gf_bs_read_int_log_idx(bs, 3, "ref_frame_idx", i);

				if (state->frame_id_numbers_present_flag) {
					u32 n = state->delta_frame_id_length_minus_2 + 2;
					/*delta_frame_id_minus_1 =*/ gf_bs_read_int_log_idx(bs, n, "delta_frame_id_minus1", i);
					//DeltaFrameId = delta_frame_id_minus_1 + 1;
					//expectedFrameId[i] = ((current_frame_id + (1 << idLen) - DeltaFrameId) % (1 << idLen));
				}
			}
			if (frame_size_override_flag && !error_resilient_mode) {
				frame_size_with_refs(bs, state, frame_size_override_flag);
			}
			else {
				av1_frame_size(bs, state, frame_size_override_flag);
				av1_render_size(bs);
			}
			frame_state->allow_high_precision_mv = 0;
			if (!force_integer_mv) {
				frame_state->allow_high_precision_mv = gf_bs_read_int_log(bs, 1, "allow_high_precision_mv");
			}

			read_interpolation_filter(bs);

			gf_bs_read_int_log(bs, 1, "is_motion_mode_switchable");
			if (!(error_resilient_mode || !state->enable_ref_frame_mvs)) {
				gf_bs_read_int_log(bs, 1, "use_ref_frame_mvs");
			}
		}
	}

	if (!FrameIsIntra) {
		u32 i;
		for (i = 0; i < AV1_REFS_PER_FRAME; i++) {
			u8 refFrame = AV1_LAST_FRAME + i;
			u8 ridx = ref_frame_idx[i];
			if (ridx >= 0) {
				u8 hint = state->RefOrderHint[ridx];
				state->OrderHints[refFrame] = hint;
				/*			if ( !enable_order_hint ) {
								RefFrameSignBias[ refFrame ] = 0;
							} else {
								RefFrameSignBias[ refFrame ] = get_relative_dist( hint, OrderHint) > 0;
							}
				*/
			}

		}
	}

	if (!(state->reduced_still_picture_header || disable_cdf_update))
		gf_bs_read_int_log(bs, 1, "disable_frame_end_update_cdf");

	if (primary_ref_frame == AV1_PRIMARY_REF_NONE) {
		//init_non_coeff_cdfs();
		av1_setup_past_independence(state);
	}
	else {
		//load_cdfs(ref_frame_idx[primary_ref_frame]);
		av1_load_previous(state, primary_ref_frame, ref_frame_idx);
	}

	av1_parse_tile_info(bs, state);
	//quantization_params( ):
	u8 base_q_idx = gf_bs_read_int(bs, 8);
	s32 DeltaQUDc = 0;
	s32 DeltaQUAc = 0;
	s32 DeltaQVDc = 0;
	s32 DeltaQVAc = 0;
	s32 DeltaQYDc = av1_delta_q(bs, "DeltaQYDc_coded", "DeltaQYDc");
	if (!state->config->monochrome) {
		u8 diff_uv_delta = 0;
		if (state->separate_uv_delta_q)
			diff_uv_delta = gf_bs_read_int(bs, 1);

		DeltaQUDc = av1_delta_q(bs, "DeltaQUDc_coded", "DeltaQUDc");
		DeltaQUAc = av1_delta_q(bs, "DeltaQUAc_coded", "DeltaQUAc");
		if (diff_uv_delta) {
			DeltaQVDc = av1_delta_q(bs, "DeltaQVDc_coded", "DeltaQVDc");
			DeltaQVAc = av1_delta_q(bs, "DeltaQVAc_coded", "DeltaQVAc");
		}
	}
	if (gf_bs_read_int_log(bs, 1, "using_qmatrix")) {
		gf_bs_read_int_log(bs, 4, "qm_y");
		gf_bs_read_int_log(bs, 4, "qm_u");
		if (!state->separate_uv_delta_q) {
			gf_bs_read_int_log(bs, 4, "qm_v");
		}
	}

	u8 seg_features_SEG_LVL_ALT_Q_enabled[8] = { 0,0,0,0,0,0,0,0 };
	s32 seg_features_SEG_LVL_ALT_Q[8] = { 0,0,0,0,0,0,0,0 };

	//segmentation_params( ):
	u8 segmentation_enabled = gf_bs_read_int_log(bs, 1, "segmentation_enabled");
	if (segmentation_enabled) {
		/*u8 segmentation_temporal_update = 0;*/
		u8 segmentation_update_data = 1;
		if (primary_ref_frame != AV1_PRIMARY_REF_NONE) {
			u8 segmentation_update_map = gf_bs_read_int_log(bs, 1, "segmentation_update_map");
			if (segmentation_update_map == 1)
				gf_bs_read_int_log(bs, 1, "segmentation_temporal_update");
			segmentation_update_data = gf_bs_read_int_log(bs, 1, "segmentation_update_data");
		}
		if (segmentation_update_data == 1) {
			u32 i, j;
			for (i = 0; i < 8/*=MAX_SEGMENTS*/; i++) {
				for (j = 0; j < 8 /*=SEG_LVL_MAX*/; j++) {
					if (/*feature_enabled = */gf_bs_read_int_log_idx2(bs, 1, "feature_enabled", i, j) == 1) {
						s32 val;
						u32 bitsToRead = Segmentation_Feature_Bits[j];
						//this is SEG_LVL_ALT_Q
						if (!j) seg_features_SEG_LVL_ALT_Q_enabled[i] = 1;

						if (Segmentation_Feature_Signed[j] == 1) {
							val = gf_bs_read_int_log_idx2(bs, 1 + bitsToRead, "signed_feature_value", i, j);
						}
						else {
							val = gf_bs_read_int_log_idx2(bs, bitsToRead, "feature_value", i, j);
						}
						if (!j) seg_features_SEG_LVL_ALT_Q[i] = val;
					}
				}
			}
			//ignore all init steps
		}

	}

	//delta_q_params():
	/*u8 delta_q_res = 0;*/
	u8 delta_q_present = 0;
	if (base_q_idx > 0) {
		delta_q_present = gf_bs_read_int_log(bs, 1, "delta_q_present");
	}
	if (delta_q_present) {
		gf_bs_read_int_log(bs, 2, "delta_q_res");
	}

	//delta_lf_params():
	u8 delta_lf_present = 0;
	/*u8 delta_lf_res = 0;
	u8 delta_lf_multi = 0;*/
	if (delta_q_present) {
		if (!allow_intrabc) {
			delta_lf_present = gf_bs_read_int_log(bs, 1, "delta_lf_present");
		}
		if (delta_lf_present) {
			gf_bs_read_int_log(bs, 2, "delta_lf_res");
			gf_bs_read_int_log(bs, 1, "delta_lf_multi");
		}
	}

	//init lossless stuff!
	u8 CodedLossless = 1;
	for (idx = 0; idx < 8; idx++) {
		u8 qindex = av1_get_qindex(GF_TRUE, idx, base_q_idx, delta_q_present, 0/*CurrentQIndex always ignored at this level of parsin*/, segmentation_enabled, seg_features_SEG_LVL_ALT_Q_enabled, seg_features_SEG_LVL_ALT_Q);
		Bool LosslessArray = (qindex == 0) && (DeltaQYDc == 0) && (DeltaQUAc == 0) && (DeltaQUDc == 0) && (DeltaQVAc == 0) && (DeltaQVDc == 0);
		if (!LosslessArray)
			CodedLossless = 0;
	}
	Bool AllLossless = CodedLossless && (state->width == state->UpscaledWidth);

	//loop_filter_params():
	if (!CodedLossless && !allow_intrabc) {
		u8 loop_filter_level_0 = gf_bs_read_int_log(bs, 6, "loop_filter_level_0");
		u8 loop_filter_level_1 = gf_bs_read_int_log(bs, 6, "loop_filter_level_1");
		if (!state->config->monochrome) {
			if (loop_filter_level_0 || loop_filter_level_1) {
				gf_bs_read_int_log(bs, 6, "loop_filter_level_2");
				gf_bs_read_int_log(bs, 6, "loop_filter_level_3");
			}
		}
		gf_bs_read_int_log(bs, 3, "loop_filter_sharpness");
		u8 loop_filter_delta_enabled = gf_bs_read_int_log(bs, 1, "loop_filter_delta_enabled");
		if (loop_filter_delta_enabled == 1) {
			u8 loop_filter_delta_update = gf_bs_read_int_log(bs, 1, "loop_filter_delta_update");
			if (loop_filter_delta_update) {
				u32 i;
				for (i = 0; i < 8/*TOTAL_REFS_PER_FRAME*/; i++) {
					u8 update_ref_delta = gf_bs_read_int_log_idx(bs, 1, "update_ref_delta", i);
					if (update_ref_delta == 1) {
						gf_bs_read_int_log_idx(bs, 1 + 6, "loop_filter_ref_deltas", i);
					}
				}
				for (i = 0; i < 2; i++) {
					u8 update_mode_delta = gf_bs_read_int_log_idx(bs, 1, "update_mode_delta", i);
					if (update_mode_delta) {
						gf_bs_read_int_log_idx(bs, 1 + 6, "loop_filter_mode_deltas", i);
					}
				}
			}
		}
	}
	//cdef_params( ):
	if (!CodedLossless && !allow_intrabc && state->enable_cdef) {
		gf_bs_read_int_log(bs, 2, "cdef_damping_minus_3");
		u8 cdef_bits = gf_bs_read_int_log(bs, 2, "cdef_bits");
		u32 i, num_cd = 1 << cdef_bits;
		for (i = 0; i < num_cd; i++) {
			gf_bs_read_int_log_idx(bs, 4, "cdef_y_pri_strength", i);
			gf_bs_read_int_log_idx(bs, 2, "cdef_y_sec_strength", i);
			if (!state->config->monochrome) {
				gf_bs_read_int_log_idx(bs, 4, "cdef_uv_pri_strength", i);
				gf_bs_read_int_log_idx(bs, 2, "cdef_uv_sec_strength", i);
			}
		}
	}

	//lr_params( ) :
	if (!AllLossless && !allow_intrabc && state->enable_restoration) {
		u32 i, nb_planes = state->config->monochrome ? 1 : 3;
		u8 UsesLr = 0;
		u8 usesChromaLr = 0;
		for (i = 0; i < nb_planes; i++) {
			u8 lr_type = gf_bs_read_int_log_idx(bs, 2, "lr_type", i);
			//FrameRestorationType[i] = Remap_Lr_Type[lr_type]
			if (lr_type != AV1_RESTORE_NONE) {
				UsesLr = 1;
				if (i > 0) {
					usesChromaLr = 1;
				}
			}
		}
		if (UsesLr) {
			if (state->use_128x128_superblock) {
				gf_bs_read_int_log(bs, 1, "lr_unit_shift_minus_1");
			}
			else {
				u8 lr_unit_shift = gf_bs_read_int_log(bs, 1, "lr_unit_shift");
				if (lr_unit_shift) {
					gf_bs_read_int_log(bs, 1, "lr_unit_extra_shift");
					//lr_unit_shift += lr_unit_extra_shift;
				}
			}
			if (state->config->chroma_subsampling_x && state->config->chroma_subsampling_y && usesChromaLr) {
				gf_bs_read_int_log(bs, 1, "lr_uv_shift");
			}
		}
	}
	//read_tx_mode():
	if (CodedLossless == 1) {
	}
	else {
		gf_bs_read_int_log(bs, 1, "tx_mode_select");
	}

	//frame_reference_mode( ):
	u8 reference_select = 0;
	if (FrameIsIntra) {
	}
	else {
		reference_select = gf_bs_read_int_log(bs, 1, "reference_select");
	}

	//skip_mode_params( ):
	u8 skipModeAllowed = 0;
	if (FrameIsIntra || !reference_select || !state->enable_order_hint) {
	}
	else {
		u32 i;
		s32 forwardIdx = -1;
		s32 backwardIdx = -1;
		s32 forwardHint = 0;
		s32 backwardHint = 0;
		for (i = 0; i < AV1_REFS_PER_FRAME; i++) {
			u8 refHint = state->RefOrderHint[ref_frame_idx[i]];
			if (av1_get_relative_dist(refHint, frame_state->order_hint, state) < 0) {
				if (forwardIdx < 0 || av1_get_relative_dist(refHint, forwardHint, state) > 0) {
					forwardIdx = i;
					forwardHint = refHint;
				}
			}
			else if (av1_get_relative_dist(refHint, frame_state->order_hint, state) > 0) {
				if (backwardIdx < 0 || av1_get_relative_dist(refHint, backwardHint, state) < 0) {
					backwardIdx = i;
					backwardHint = refHint;
				}
			}
		}
		if (forwardIdx < 0) {
			skipModeAllowed = 0;
		}
		else if (backwardIdx >= 0) {
			skipModeAllowed = 1;
			//SkipModeFrame[0] = AV1_LAST_FRAME + MIN(forwardIdx, backwardIdx);
			//SkipModeFrame[1] = AV1_LAST_FRAME + MAX(forwardIdx, backwardIdx);
		}
		else {
			s32 secondForwardIdx = -1;
			s32 secondForwardHint = 0;
			for (i = 0; i < AV1_REFS_PER_FRAME; i++) {
				u8 refHint = state->RefOrderHint[ref_frame_idx[i]];
				if (av1_get_relative_dist(refHint, forwardHint, state) < 0) {
					if (secondForwardIdx < 0 || av1_get_relative_dist(refHint, secondForwardHint, state) > 0) {
						secondForwardIdx = i;
						secondForwardHint = refHint;
					}
				}
			}
			if (secondForwardIdx < 0) {
				skipModeAllowed = 0;
			}
			else {
				skipModeAllowed = 1;
				//SkipModeFrame[ 0 ] = LAST_FRAME + Min(forwardIdx, secondForwardIdx)
				//SkipModeFrame[ 1 ] = LAST_FRAME + Max(forwardIdx, secondForwardIdx)
			}
		}
	}
	if (skipModeAllowed) {
		gf_bs_read_int_log(bs, 1, "skip_mode_present");
	}

	if (FrameIsIntra || error_resilient_mode || !state->enable_warped_motion) {

	}
	else {
		gf_bs_read_int_log(bs, 1, "allow_warped_motion");
	}

	gf_bs_read_int_log(bs, 1, "reduced_tx");

	//global_motion_params( )
	u32 ref;
	for (ref = AV1_LAST_FRAME; ref <= AV1_ALTREF_FRAME; ref++) {
		u32 i;
		for (i = 0; i < 6; i++) {
			state->GmParams.coefs[ref][i] = ((i % 3 == 2) ? 1 << WARPEDMODEL_PREC_BITS : 0);
		}
	}
	if (!FrameIsIntra) {
		u32 refs;
		for (refs = AV1_LAST_FRAME; refs <= AV1_ALTREF_FRAME; refs++) {
			u8 type = AV1_GMC_IDENTITY;
			Bool is_global = gf_bs_read_int_log_idx(bs, 1, "is_global", refs);
			if (is_global) {
				Bool is_rot_zoom = gf_bs_read_int_log_idx(bs, 1, "is_rot_zoom", refs);
				if (is_rot_zoom) {
					type = AV1_GMC_ROTZOOM;
				}
				else {
					Bool is_trans = gf_bs_read_int_log_idx(bs, 1, "is_translation", refs);
					type = is_trans ? AV1_GMC_TRANSLATION : AV1_GMC_AFFINE;

				}
			}

			if (type >= AV1_GMC_ROTZOOM) {
				av1_read_global_param(state, bs, type, refs, 2);
				av1_read_global_param(state, bs, type, refs, 3);
				if (type == AV1_GMC_AFFINE) {
					av1_read_global_param(state, bs, type, refs, 4);
					av1_read_global_param(state, bs, type, refs, 5);
				}
				else {
					state->GmParams.coefs[refs][4] = -state->GmParams.coefs[refs][3];
					state->GmParams.coefs[refs][5] = state->GmParams.coefs[refs][2];

				}
			}
			if (type >= AV1_GMC_TRANSLATION) {
				av1_read_global_param(state, bs, type, refs, 0);
				av1_read_global_param(state, bs, type, refs, 1);
			}
		}
	}

	//film_grain_params()
	if (!state->film_grain_params_present || (!state->frame_state.show_frame && !showable_frame)) {
	}
	else {
		u8 apply_grain = gf_bs_read_int_log(bs, 1, "apply_grain");
		if (apply_grain) {
			gf_bs_read_int_log(bs, 16, "grain_seed");
			u8 update_grain = 1;
			if (state->frame_state.frame_type == AV1_INTER_FRAME) {
				update_grain = gf_bs_read_int_log(bs, 1, "update_grain");
			}
			if (!update_grain) {
				gf_bs_read_int_log(bs, 3, "film_grain_params_ref_idx");
			}
			else {
				u32 i, num_y_points = gf_bs_read_int_log(bs, 4, "num_y_points");
				for (i = 0; i < num_y_points; i++) {
					gf_bs_read_int_log_idx(bs, 8, "point_y_value", i);
					gf_bs_read_int_log_idx(bs, 8, "point_y_scaling", i);
				}
				u8 chroma_scaling_from_luma = 0;
				if (!state->config->monochrome)
					chroma_scaling_from_luma = gf_bs_read_int_log(bs, 1, "chroma_scaling_from_luma");

				u8 num_cb_points = 0;
				u8 num_cr_points = 0;
				if (state->config->monochrome || chroma_scaling_from_luma ||
					((state->config->chroma_subsampling_x == 1) && (state->config->chroma_subsampling_y == 1) && (num_y_points == 0))
					) {
				}
				else {
					num_cb_points = gf_bs_read_int_log(bs, 4, "num_cb_points");
					for (i = 0; i < num_cb_points; i++) {
						gf_bs_read_int_log_idx(bs, 8, "point_cb_value", i);
						gf_bs_read_int_log_idx(bs, 8, "point_cb_scaling", i);
					}
					num_cr_points = gf_bs_read_int_log(bs, 4, "num_cr_points");
					for (i = 0; i < num_cr_points; i++) {
						gf_bs_read_int_log_idx(bs, 8, "point_cr_value", i);
						gf_bs_read_int_log_idx(bs, 8, "point_cr_scaling", i);
					}
				}
				gf_bs_read_int_log(bs, 2, "grain_scaling_minus_8");
				u8 ar_coeff_lag = gf_bs_read_int_log(bs, 2, "ar_coeff_lag");
				u16 numPosLuma = 2 * ar_coeff_lag * (ar_coeff_lag + 1);
				u16 numPosChroma = numPosLuma;
				if (num_y_points) {
					numPosChroma = numPosLuma + 1;
					for (i = 0; i < numPosLuma; i++) {
						gf_bs_read_int_log_idx(bs, 8, "ar_coeffs_y_plus_128", i);
					}
				}
				if (chroma_scaling_from_luma || num_cb_points) {
					for (i = 0; i < numPosChroma; i++) {
						gf_bs_read_int_log_idx(bs, 8, "ar_coeffs_cb_plus_128", i);
					}
				}
				if (chroma_scaling_from_luma || num_cr_points) {
					for (i = 0; i < numPosChroma; i++) {
						gf_bs_read_int_log_idx(bs, 8, "ar_coeffs_cr_plus_128", i);
					}
				}
				gf_bs_read_int_log(bs, 2, "ar_coeff_shift_minus_6");
				gf_bs_read_int_log(bs, 2, "grain_scale_shift");
				if (num_cb_points) {
					gf_bs_read_int_log(bs, 8, "cb_mult");
					gf_bs_read_int_log(bs, 8, "cb_luma_mult");
					gf_bs_read_int_log(bs, 9, "cb_offset");
				}
				if (num_cr_points) {
					gf_bs_read_int_log(bs, 8, "cr_mult");
					gf_bs_read_int_log(bs, 8, "cr_luma_mult");
					gf_bs_read_int_log(bs, 9, "cr_offset");
				}
				gf_bs_read_int_log(bs, 1, "overlap_flag");
				gf_bs_read_int_log(bs, 1, "clip_to_restricted_range");
			}
		}
	}

	//end of uncompressed header !!
}


u64 gf_av1_leb128_read(GF_BitStream *bs, u8 *opt_Leb128Bytes) {
	u64 value = 0;
	u8 Leb128Bytes = 0, i = 0;
	for (i = 0; i < 8; i++) {
		u8 leb128_byte = gf_bs_read_u8(bs);
		value |= ( ((u64) (leb128_byte & 0x7f)) << (i * 7));
		Leb128Bytes += 1;
		if (!(leb128_byte & 0x80)) {
			break;
		}
	}

	if (opt_Leb128Bytes) {
		*opt_Leb128Bytes = Leb128Bytes;
	}
	return value;
}


Bool gf_eac3_parser_bs(GF_BitStream *bs, GF_AC3Config *hdr, Bool full_parse)
{
	u32 fscod, bsid, ac3_mod, freq, framesize, syncword, substreamid, lfon, channels, numblkscod, strmtyp, frmsiz;
	u64 pos;
	u16 chanmap;
	static u32 numblks[4] = {1, 2, 3, 6};

	if (!hdr || (gf_bs_available(bs) < 6))
		return GF_FALSE;
	if (!AC3_FindSyncCodeBS(bs))
		return GF_FALSE;

	pos = gf_bs_get_position(bs);
	framesize = 0;
	numblkscod = 0;
	memset(hdr, 0, sizeof(GF_AC3Config));

block:
	syncword = gf_bs_read_u16(bs);
	if (syncword != 0x0B77) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[E-AC3] Wrong sync word detected (0x%X - expecting 0x0B77).\n", syncword));
		return GF_FALSE;
	}

	strmtyp = gf_bs_read_int_log(bs, 2, "strmtyp");
	substreamid = gf_bs_read_int_log(bs, 3, "substreamid");
	//next main (independent) AU, done with this frame
	if ((strmtyp!=0x1) && ((hdr->substreams >> substreamid) & 0x1)) {
		hdr->framesize = framesize;
		gf_bs_seek(bs, pos);
		return GF_TRUE;
	}

	frmsiz = gf_bs_read_int_log(bs, 11, "frmsiz");
	framesize += 2 * (1 + frmsiz);
	fscod = gf_bs_read_int_log(bs, 2, "fscod");
	if (fscod == 0x3) {
		fscod = gf_bs_read_int_log(bs, 2, "fscod2");
		numblkscod += 6;
	}
	else {
		numblkscod += gf_bs_read_int_log(bs, 2, "numblkscod");
	}
	assert(numblkscod <= 9);

	if ((hdr->substreams >> substreamid) & 0x1) {
		//we still have sync frames following
		if (substreamid) {
			if (gf_bs_seek(bs, pos + framesize) != GF_OK) {
				gf_bs_seek(bs, pos);
				return GF_FALSE;
			}
			if ((gf_bs_available(bs) < 6) || !AC3_FindSyncCodeBS(bs)) {
				gf_bs_seek(bs, pos);
				return GF_FALSE;
			}
			goto block;
		}
	}

	hdr->substreams |= (1 << substreamid);

	switch (fscod) {
	case 0:
		freq = 48000;
		break;
	case 1:
		freq = 44100;
		break;
	case 2:
		freq = 32000;
		break;
	default:
		return GF_FALSE;
	}

	ac3_mod = gf_bs_read_int_log(bs, 3, "ac3_mod");
	lfon = gf_bs_read_int_log(bs, 1, "lfon");
	bsid = gf_bs_read_int_log(bs, 5, "bsid");
	if (!substreamid && (bsid != 16/*E-AC3*/))
		return GF_FALSE;
	gf_bs_read_int_log(bs, 5, "dialnorm");
	if (gf_bs_read_int_log(bs, 1, "compre")) {
		gf_bs_read_int_log(bs, 8, "compr");
	}
	if (ac3_mod==0) {
		gf_bs_read_int_log(bs, 5, "dialnorm2");
		if (gf_bs_read_int_log(bs, 1, "compr2e")) {
			gf_bs_read_int_log(bs, 8, "compr2");
		}
	}
	chanmap = 0;
	if (strmtyp==0x1) {
		if (gf_bs_read_int_log(bs, 1, "chanmape")) {
			chanmap = gf_bs_read_int_log(bs, 16, "chanmap");
		}
	}

	channels = ac3_mod_to_chans[ac3_mod];
	if (lfon)
		channels += 1;

	hdr->bitrate = 0;
	hdr->sample_rate = freq;
	hdr->framesize = framesize;
	if (strmtyp != 1) {
		hdr->channels = channels;
		hdr->streams[substreamid].lfon = lfon;
		if (full_parse) {
			hdr->streams[substreamid].bsid = bsid;
			hdr->streams[substreamid].bsmod = 0;
			hdr->streams[substreamid].acmod = ac3_mod;
			hdr->streams[substreamid].fscod = fscod;
			hdr->brcode = 0;
		}
		hdr->nb_streams++;
		//not clear if this is only for the independent streams
		hdr->brcode += ((frmsiz+1) * freq) / (numblks[numblkscod]*16) / 1000;

		if (lfon)
			hdr->channels += 1;

	} else {
		hdr->streams[substreamid].nb_dep_sub = substreamid;
		hdr->streams[substreamid].chan_loc |= chanmap;
	}

	if (numblkscod < 6) { //we need 6 blocks to make a sample
		if (gf_bs_seek(bs, pos + framesize) != GF_OK) {
			gf_bs_seek(bs, pos);
			return GF_FALSE;
		}

		if ((gf_bs_available(bs) < 6) || !AC3_FindSyncCodeBS(bs))
			return GF_FALSE;
		goto block;
	}

	gf_bs_seek(bs, pos);

	return GF_TRUE;
}


Bool gf_hevc_slice_is_IDR(HEVCState *hevc)
{
	if (hevc->sei.recovery_point.valid)
	{
		hevc->sei.recovery_point.valid = 0;
		return GF_TRUE;
	}
	switch (hevc->s_info.nal_unit_type) {
	case GF_HEVC_NALU_SLICE_IDR_W_DLP:
	case GF_HEVC_NALU_SLICE_IDR_N_LP:
		return GF_TRUE;
	default:
		return GF_FALSE;
	}
}


static s32 SVC_ReadNal_header_extension(GF_BitStream *bs, SVC_NALUHeader *NalHeader)
{
	gf_bs_read_int_log(bs, 1, "reserved_one_bit");
	NalHeader->idr_pic_flag = gf_bs_read_int_log(bs, 1, "idr_flag");
	NalHeader->priority_id = gf_bs_read_int_log(bs, 6, "priority_id");
	gf_bs_read_int_log(bs, 1, "no_inter_layer_pred_flag");
	NalHeader->dependency_id = gf_bs_read_int_log(bs, 3, "DependencyId");
	NalHeader->quality_id = gf_bs_read_int_log(bs, 4, "quality_id");
	NalHeader->temporal_id = gf_bs_read_int_log(bs, 3, "temporal_id");
	gf_bs_read_int_log(bs, 1, "use_ref_base_pic_flag");
	gf_bs_read_int_log(bs, 1, "discardable_flag");
	gf_bs_read_int_log(bs, 1, "output_flag");
	gf_bs_read_int_log(bs, 2, "reserved_three_2bits");
	return 1;
}


static void av1_setup_past_independence(AV1State *state)
{
	u32 ref, i;
	for (ref = AV1_LAST_FRAME; ref <= AV1_ALTREF_FRAME; ref++) {
		for (i = 0; i <= 5; i++) {
			state->PrevGmParams.coefs[ref][i] = ((i % 3 == 2) ? 1 << WARPEDMODEL_PREC_BITS : 0);
		}
	}
}


u32 gf_media_nalu_emulation_bytes_add_count(u8 *buffer, u32 nal_size)
{
	u32 i = 0, emulation_bytes_count = 0;
	u8 num_zero = 0;

	while (i < nal_size) {
		/*ISO 14496-10: "Within the NAL unit, any four-byte sequence that starts with 0x000003
		other than the following sequences shall not occur at any byte-aligned position:
		\96 0x00000300
		\96 0x00000301
		\96 0x00000302
		\96 0x00000303"
		*/
		if (num_zero == 2 && (u8)buffer[i] < 0x04) {
			/*emulation code found*/
			num_zero = 0;
			emulation_bytes_count++;
			if (!buffer[i])
				num_zero = 1;
		}
		else {
			if (!buffer[i])
				num_zero++;
			else
				num_zero = 0;
		}
		i++;
	}
	return emulation_bytes_count;
}


s32 gf_mv12_next_start_code(unsigned char *pbuffer, u32 buflen, u32 *optr, u32 *scode)
{
	u32 value;
	u32 offset;

	if (buflen < 4) return -1;
	for (offset = 0; offset < buflen - 3; offset++, pbuffer++) {
#ifdef GPAC_BIG_ENDIAN
		value = *(u32 *)pbuffer >> 8;
#else
		value = (pbuffer[0] << 16) | (pbuffer[1] << 8) | (pbuffer[2] << 0);
#endif

		if (value == MPEG12_START_CODE_PREFIX) {
			*optr = offset;
			*scode = (value << 8) | pbuffer[3];
			return 0;
		}
	}
	return -1;
}


static void av1_parse_sequence_header_obu(GF_BitStream *bs, AV1State *state)
{
	u8 buffer_delay_length_minus_1 = 0;
	state->frame_state.seen_seq_header = GF_TRUE;
	state->config->seq_profile = gf_bs_read_int_log(bs, 3, "seq_profile");
	state->still_picture = gf_bs_read_int_log(bs, 1, "still_picture");
	state->reduced_still_picture_header = gf_bs_read_int_log(bs, 1, "reduced_still_picture_header");
	if (state->reduced_still_picture_header) {
		//timing_info_present_flag = GF_FALSE;
		//initial_display_delay_present_flag = GF_FALSE;
		state->operating_points_count = 1;
		state->config->seq_level_idx_0 = gf_bs_read_int_log(bs, 5, "seq_level_idx_0");
	}
	else {
		u8 i = 0;
		Bool initial_display_delay_present_flag;
		Bool timing_info_present_flag = gf_bs_read_int_log(bs, 1, "timing_info_present_flag");
		if (timing_info_present_flag) {
			timing_info(bs, state);
			state->decoder_model_info_present_flag = gf_bs_read_int_log(bs, 1, "decoder_model_info_present_flag");
			if (state->decoder_model_info_present_flag) {
				decoder_model_info(state, bs);
			}
		}
		else {
			state->decoder_model_info_present_flag = GF_FALSE;
		}
		initial_display_delay_present_flag = gf_bs_read_int_log(bs, 1, "initial_display_delay_present_flag");
		state->operating_points_count = 1 + gf_bs_read_int_log(bs, 5, "operating_points_count_minus1");
		for (i = 0; i < state->operating_points_count; i++) {
			u8 seq_level_idx_i, seq_tier = 0;

			state->operating_point_idc[i] = gf_bs_read_int_log_idx(bs, 12, "operating_point_idc", i);

			seq_level_idx_i = gf_bs_read_int_log_idx(bs, 5, "seq_level_idx", i);
			if (i == 0) state->config->seq_level_idx_0 = seq_level_idx_i;

			if (seq_level_idx_i > 7) {
				seq_tier = gf_bs_read_int_log_idx(bs, 1, "seq_tier", i);
			}
			if (i == 0) state->config->seq_tier_0 = seq_tier;

			if (state->decoder_model_info_present_flag) {
				state->decoder_model_present_for_this_op[i] = gf_bs_read_int_log_idx(bs, 1, "decoder_model_present_for_this_op", i);
				if (state->decoder_model_present_for_this_op[i]) {
					operating_parameters_info(bs, i, buffer_delay_length_minus_1);
				}
			}
			else {
				state->decoder_model_present_for_this_op[i] = 0;
			}
			if (initial_display_delay_present_flag) {
				if (gf_bs_read_int_log_idx(bs, 1, "initial_display_delay_present_for_this_op", i) ) {
					gf_bs_read_int_log_idx(bs, 4, "initial_display_delay_minus1", i);
				}
			}
		}
	}

	//operatingPoint = av1_choose_operating_point(bs);
	state->OperatingPointIdc = 0;//TODO: operating_point_idc[operatingPoint];

	state->frame_width_bits_minus_1 = gf_bs_read_int_log(bs, 4, "frame_width_bits_minus1");
	state->frame_height_bits_minus_1 = gf_bs_read_int_log(bs, 4, "frame_height_bits_minus1");
	state->width = gf_bs_read_int_log(bs, state->frame_width_bits_minus_1 + 1, "width_minus1") + 1;
	state->height = gf_bs_read_int_log(bs, state->frame_height_bits_minus_1 + 1, "height_minus1") + 1;
	state->sequence_width = state->width;
	state->sequence_height = state->height;
	state->frame_id_numbers_present_flag = GF_FALSE;
	if (!state->reduced_still_picture_header) {
		state->frame_id_numbers_present_flag = gf_bs_read_int_log(bs, 1, "frame_id_numbers_present_flag");
	}
	if (state->frame_id_numbers_present_flag) {
		state->delta_frame_id_length_minus_2 = gf_bs_read_int_log(bs, 4, "delta_frame_id_length_minus2");
		state->additional_frame_id_length_minus_1 = gf_bs_read_int_log(bs, 3, "additional_frame_id_length_minus1");
	}
	state->use_128x128_superblock = gf_bs_read_int_log(bs, 1, "use_128x128_superblock");
	gf_bs_read_int_log(bs, 1, "enable_filter_intra");
	gf_bs_read_int_log(bs, 1, "enable_intra_edge_filter");
	if (state->reduced_still_picture_header) {
		/*enable_interintra_compound = 0;
		enable_masked_compound = 0;
		enable_dual_filter = 0;
		enable_jnt_comp = 0;
		enable_ref_frame_mvs = 0;*/
		state->enable_warped_motion = 0;
		state->enable_order_hint = GF_FALSE;
		state->OrderHintBits = 0;
		state->seq_force_integer_mv = 2/*SELECT_INTEGER_MV*/;
		state->seq_force_screen_content_tools = 2/*SELECT_SCREEN_CONTENT_TOOLS*/;
	}
	else {
		Bool seq_choose_screen_content_tools;
		gf_bs_read_int_log(bs, 1, "enable_interintra_compound");
		gf_bs_read_int_log(bs, 1, "enable_masked_compound");
		state->enable_warped_motion = gf_bs_read_int_log(bs, 1, "enable_warped_motion");
		gf_bs_read_int_log(bs, 1, "enable_dual_filter");
		state->enable_order_hint = gf_bs_read_int_log(bs, 1, "enable_order_hint");
		if (state->enable_order_hint) {
			gf_bs_read_int_log(bs, 1, "enable_jnt_comp");
			state->enable_ref_frame_mvs = gf_bs_read_int_log(bs, 1, "enable_ref_frame_mvs");
		}
		else {
			/*enable_jnt_comp =  0*/;
			/*enable_ref_frame_mvs = 0*/;
		}
		seq_choose_screen_content_tools = gf_bs_read_int_log(bs, 1, "seq_choose_screen_content_tools");
		state->seq_force_screen_content_tools = 0;
		if (seq_choose_screen_content_tools) {
			state->seq_force_screen_content_tools = 2/*SELECT_SCREEN_CONTENT_TOOLS*/;
		}
		else {
			state->seq_force_screen_content_tools = gf_bs_read_int_log(bs, 1, "seq_force_screen_content_tools");
		}

		state->seq_force_integer_mv = 0;
		if (state->seq_force_screen_content_tools > 0) {
			const Bool seq_choose_integer_mv = gf_bs_read_int_log(bs, 1, "seq_choose_integer_mv");
			if (seq_choose_integer_mv) {
				state->seq_force_integer_mv = 2/*SELECT_INTEGER_MV*/;
			}
			else {
				state->seq_force_integer_mv = gf_bs_read_int_log(bs, 1, "seq_force_integer_mv");
			}
		}
		else {
			state->seq_force_integer_mv = 2/*SELECT_INTEGER_MV*/;
		}
		if (state->enable_order_hint) {
			u8 order_hint_bits_minus_1 = gf_bs_read_int_log(bs, 3, "order_hint_bits_minus1");
			state->OrderHintBits = order_hint_bits_minus_1 + 1;
		}
		else {
			state->OrderHintBits = 0;
		}
	}

	state->enable_superres = gf_bs_read_int_log(bs, 1, "enable_superres");
	state->enable_cdef = gf_bs_read_int_log(bs, 1, "enable_cdef");
	state->enable_restoration = gf_bs_read_int_log(bs, 1, "enable_restoration");
	av1_color_config(bs, state);
	state->film_grain_params_present = gf_bs_read_int_log(bs, 1, "film_grain_params_present");
}


GF_Err gf_m4v_get_config(u8 *rawdsi, u32 rawdsi_size, GF_M4VDecSpecInfo *dsi)
{
	GF_Err e;
	GF_M4VParser *vparse;
	if (!rawdsi || !rawdsi_size) return GF_NON_COMPLIANT_BITSTREAM;
	vparse = gf_m4v_parser_new(rawdsi, rawdsi_size, 0);
	e = gf_m4v_parse_config(vparse, dsi);
	dsi->next_object_start = (u32)vparse->current_object_start;
	gf_m4v_parser_del(vparse);
	return e < 0 ? e : GF_OK;
}


GF_Err gf_media_vp9_parse_superframe(GF_BitStream *bs, u64 ivf_frame_size, u32 *num_frames_in_superframe, u32 frame_sizes[VP9_MAX_FRAMES_IN_SUPERFRAME], u32 *superframe_index_size)
{
	u32 byte, bytes_per_framesize;
	u64 pos = gf_bs_get_position(bs), i = 0;
	GF_Err e;

	assert(bs && num_frames_in_superframe);

	/*initialize like there is no superframe*/
	memset(frame_sizes, 0, VP9_MAX_FRAMES_IN_SUPERFRAME * sizeof(frame_sizes[0]));
	*num_frames_in_superframe = 1;
	frame_sizes[0] = (u32)ivf_frame_size;
	*superframe_index_size = 0;

	e = gf_bs_seek(bs, pos + ivf_frame_size - 1);
	if (e) return e;

	byte = gf_bs_read_u8(bs);
	if ((byte & 0xe0) != 0xc0)
		goto exit; /*no superframe*/

	bytes_per_framesize = 1 + ((byte & 0x18) >> 3);
	*num_frames_in_superframe = (u32)(1 + (byte & 0x7));

	/*superframe_index()*/
	*superframe_index_size = 2 + bytes_per_framesize * *num_frames_in_superframe;
	gf_bs_seek(bs, pos + ivf_frame_size - *superframe_index_size);
	byte = gf_bs_read_u8(bs);
	if ((byte & 0xe0) != 0xc0)
		goto exit; /*no superframe*/

	frame_sizes[0] = 0;
	for (i = 0; i < *num_frames_in_superframe; ++i) {
		gf_bs_read_data(bs, (char*)(frame_sizes + i), bytes_per_framesize);
	}

exit:
	gf_bs_seek(bs, pos);
	return e;
}


static void av1_frame_size(GF_BitStream *bs, AV1State *state, Bool frame_size_override_flag)
{
	if (frame_size_override_flag) {
		u32 frame_width_minus_1, frame_height_minus_1;
		u8 n = state->frame_width_bits_minus_1 + 1;
		frame_width_minus_1 = gf_bs_read_int_log(bs, n, "frame_width_minus_1");
		n = state->frame_height_bits_minus_1 + 1;
		frame_height_minus_1 = gf_bs_read_int_log(bs, n, "frame_height_minus_1");
		state->width = frame_width_minus_1 + 1;
		state->height = frame_height_minus_1 + 1;
	} else {
		state->width = state->sequence_width;
		state->height = state->sequence_height;
	}
	superres_params(bs, state);
	//compute_image_size(); //no bits
}


void gf_media_reduce_aspect_ratio(u32 *width, u32 *height)
{
	u32 i = 0;
	u32 w = *width;
	u32 h = *height;
	while (std_par[i].w) {
		if (std_par[i].w * h == std_par[i].h * w) {
			*width = std_par[i].w;
			*height = std_par[i].h;
			return;
		}
		i++;
	}
	//not standard one, reduce by power of 2
	i = 2;
	while (1) {
		if (w <= i) return;
		if (h <= i) return;

		if (w % i) return;
		if (h % i) return;
		*width = w / i;
		*height = h / i;
		i *= 2;
	}
}


u16 gf_mp3_frame_size(u32 hdr)
{
	u8 version = gf_mp3_version(hdr);
	u8 layer = gf_mp3_layer(hdr);
	u32 pad = ((hdr >> 9) & 0x1) ? 1 : 0;
	u32 bitrate = gf_mp3_bit_rate(hdr);
	u32 samplerate = gf_mp3_sampling_rate(hdr);

	u32 frameSize = 0;
	if (!samplerate || !bitrate) return 0;

	if (layer == 1) {
		frameSize = ((12 * bitrate / samplerate) + pad) * 4;
	}
	else {
		u32 slots_per_frame = 144;
		if ((layer == 3) && !(version & 1)) slots_per_frame = 72;
		frameSize = (slots_per_frame * bitrate / samplerate) + pad;
	}
	return (u16)frameSize;
}