nginx-mod-rtmp/ngx_rtmp_shared.c

128 lines
2.7 KiB
C

/*
* Copyright (C) Roman Arutyunyan
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include "ngx_rtmp.h"
ngx_chain_t *
ngx_rtmp_alloc_shared_buf(ngx_rtmp_core_srv_conf_t *cscf)
{
u_char *p;
ngx_chain_t *out;
ngx_buf_t *b;
size_t size;
if (cscf->free) {
out = cscf->free;
cscf->free = out->next;
} else {
size = cscf->chunk_size + NGX_RTMP_MAX_CHUNK_HEADER;
p = ngx_pcalloc(cscf->pool, NGX_RTMP_REFCOUNT_BYTES
+ sizeof(ngx_chain_t)
+ sizeof(ngx_buf_t)
+ size);
if (p == NULL) {
return NULL;
}
p += NGX_RTMP_REFCOUNT_BYTES;
out = (ngx_chain_t *)p;
p += sizeof(ngx_chain_t);
out->buf = (ngx_buf_t *)p;
p += sizeof(ngx_buf_t);
out->buf->start = p;
out->buf->end = p + size;
}
out->next = NULL;
b = out->buf;
b->pos = b->last = b->start + NGX_RTMP_MAX_CHUNK_HEADER;
b->memory = 1;
/* buffer has refcount =1 when created! */
ngx_rtmp_ref_set(out, 1);
return out;
}
void
ngx_rtmp_free_shared_chain(ngx_rtmp_core_srv_conf_t *cscf, ngx_chain_t *in)
{
ngx_chain_t *cl;
if (ngx_rtmp_ref_put(in)) {
return;
}
for (cl = in; ; cl = cl->next) {
/* FIXME: Don't create circular chains in the first place */
if (cl->next == NULL || cl->next == in) {
cl->next = cscf->free;
cscf->free = in;
return;
}
}
}
ngx_chain_t *
ngx_rtmp_append_shared_bufs(ngx_rtmp_core_srv_conf_t *cscf,
ngx_chain_t *head, ngx_chain_t *in)
{
ngx_chain_t *l, **ll;
u_char *p;
size_t size;
ll = &head;
p = in->buf->pos;
l = head;
if (l) {
for(; l->next; l = l->next);
ll = &l->next;
}
for ( ;; ) {
if (l == NULL || l->buf->last == l->buf->end) {
l = ngx_rtmp_alloc_shared_buf(cscf);
if (l == NULL || l->buf == NULL) {
break;
}
*ll = l;
ll = &l->next;
}
while (l->buf->end - l->buf->last >= in->buf->last - p) {
l->buf->last = ngx_cpymem(l->buf->last, p,
in->buf->last - p);
in = in->next;
if (in == NULL) {
goto done;
}
p = in->buf->pos;
}
size = l->buf->end - l->buf->last;
l->buf->last = ngx_cpymem(l->buf->last, p, size);
p += size;
}
done:
*ll = NULL;
return head;
}