Welcome! Log In Create A New Profile

Advanced

Video Streaming using non http backend, Ref ngx_drizzle

Posted by Sammy Raul 
Hi All,

I am trying to stream video it can be mp4, flv anything using nginx.

The video streams in the form of 1024 size will be available from the
backend non-http server.

For achieveing this I followed the ngx_http_drizzle source.

I wrote an upstream handler and followed most of the source code from
ngx_http_drizzle.

I have few questions or to be more precise I did not understood how the
output from drizzle is being streamed to the client.

1) In ngx_http_drizzle_output.c the function ngx_http_drizzle_submit_mem is
the place where it is setting the output filter, Is it also sending the
response i.e the stream to the client at this point, or it is some other
function?

2) What I need to do to send my video contents to the client, I followed
the drizzle example but setting output and sending stream to the client,
how I can achieve this. I have 1024B avaialble at one point and I want to
send this to the client till the backend server has no stream to send and
the client should be able to play the content.

3) Is it possible to send the video stream to the client with the browser.


Can someone who knows about this, please explain how it works. What changes
I need to make.
It would be highly appreciated if anyone explains this.

Thanks,
Raul
_______________________________________________
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx
Anything on this, just a small hint on how I can configure the output filter
would be highly appreciated.

Thanks,
Raul

--
View this message in context: http://nginx.2469901.n2.nabble.com/Video-Streaming-using-non-http-backend-Ref-ngx-drizzle-tp7580235p7580237.html
Sent from the nginx mailing list archive at Nabble.com.

_______________________________________________
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx
Hello!

On Mon, Jun 4, 2012 at 10:01 AM, Sammy Raul <[email protected]> wrote:
> I am trying to stream video it can be mp4, flv anything using nginx.
>
> The video streams in the form of 1024 size will be available from the
> backend non-http server.
>

I think this can be done trivially via ngx_lua module while still
achieving good performance. Here is a small example that demonstrates
how to meet your requirements with a little Lua:

location /api {
content_by_lua '
local sock, err = ngx.socket.tcp()
if not sock then
ngx.log(ngx.ERR, "failed to get socket: ", err)
ngx.exit(500)
end

sock:settimeout(1000) -- 1 sec

local ok, err = sock:connect("some.backend.host", 12345)
if not ok then
ngx.log(ngx.ERR, "failed to connect to upstream: ", err)
ngx.exit(502)
end

local bytes, err = sock:send("some query")
if not bytes then
ngx.log(ngx.ERR, "failed to send query: ", err)
ngx.exit(502)
end

while true do
local data, err, partial = sock:receive(1024)
if not data then
if err == "closed" then
if partial then
ngx.print(partial)
ngx.eof()
ngx.exit(ngx.OK)
end
else
ngx.log(ngx.ERR, "error reading data: ", err)
ngx.exit(502)
end
else
ngx.print(data)
ngx.flush(true)
end
end
';
}

See the documentation for details:

http://wiki.nginx.org/HttpLuaModule

> For achieveing this I followed the ngx_http_drizzle source.
>
> I wrote an upstream handler and followed most of the source code from
> ngx_http_drizzle.
>

As the author of ngx_drizzle, I suggest you start from trying out
ngx_lua. Customizing ngx_drizzle for your needs requires a *lot* of
work. The C approach should only be attempted when Lua is indeed too
slow for your purpose, which is not very likely for many applications
though.

Also, please note that ngx_drizzle does not support strict
non-buffered data output. So, for downstream connections that are slow
to write, data will still accumulate in RAM without control. On the
other hand, the ngx_lua sample given above does not suffer from this
issue.

> I have few questions or to be more precise I did not understood how the
> output from drizzle is being streamed to the client.
>
> 1) In ngx_http_drizzle_output.c the function ngx_http_drizzle_submit_mem is
> the place where it is setting the output filter, Is it also sending the
> response i.e the stream to the client at this point, or it is some other
> function?
>

Nope. Sending output buffers to the output filter chain is done by the
ngx_http_drizzle_output_bufs function.

> 2) What I need to do to send my video contents to the client, I followed the
> drizzle example but setting output and sending stream to the client, how I
> can achieve this. I have 1024B avaialble at one point and I want to send
> this to the client till the backend server has no stream to send and the
> client should be able to play the content.
>

Basically, you can call the ngx_http_output_filter function, just as
other nginx upstream modules.

> 3) Is it possible to send the video stream to the client with the browser.
>

I do not quite follow this question.

Best regards,
-agentzh

_______________________________________________
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx
Thanks agentzh for explaining so well.

When I am connected to the backend server I am getting buffer which I am
sending to the client like this:

ngx_int_t
ngx_http_ccn_send_output_bufs(ngx_http_request_t *r,
ngx_http_upstream_ccn_peer_data_t *dp, const unsigned char *data,
size_t data_size)
{
ngx_http_upstream_t *u = r->upstream;
ngx_int_t rc;
ngx_buf_t *b;
ngx_chain_t out;

/* allocate a buffer for your response body */
b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
if (b == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}

/* attach this buffer to the buffer chain */
out.buf = b;
out.next = NULL;

/* adjust the pointers of the buffer */
b->pos = (u_char *) data;
b->last = b->pos + data_size - 1;
b->memory = 1; /* this buffer is in memory */
b->last_buf = 1; /* this is the last buffer in the buffer chain */


if ( ! u->header_sent ) {
fprintf(stdout, "ngx_http_ccn_send_output_bufs u->header_sent\n");
r->headers_out.status = NGX_HTTP_OK;

/* set the Content-Type header */

r->headers_out.content_type.data =
(u_char *) "application/octet-stream";

r->headers_out.content_type.len =
sizeof("application/octet-stream") - 1;

r->headers_out.content_type_len =
sizeof("application/octet-stream") - 1;

rc = ngx_http_send_header(r);

if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
fprintf(stdout, "ngx_http_ccn_send_output_bufs header sent
error\n");
return rc;
}

u->header_sent = 1;
fprintf(stdout, "ngx_http_ccn_send_output_bufs
u->header_sent=%d\n",u->header_sent);
}

rc = ngx_http_output_filter(r, &out);

if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
return rc;
}

this function I am calling everytime I am receiving data (1024) from the
backend
when it is end of stream I am calling
ngx_http_finalize_request(r, rc);

but it is not working as expected which is like playing the video file in
the browser

I didn't follow the lua module yet, but will look into it

Is there anything I am doing wrong while setting the output buffer, do I
need to change this line b->last_buf = 1;
or something else.

Thanks,
Raul

--
View this message in context: http://nginx.2469901.n2.nabble.com/Video-Streaming-using-non-http-backend-Ref-ngx-drizzle-tp7580235p7580247.html
Sent from the nginx mailing list archive at Nabble.com.

_______________________________________________
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx
Hello!

On Tue, Jun 5, 2012 at 12:06 PM, sammy_raul <[email protected]> wrote:
>
>    /* adjust the pointers of the buffer */
>    b->pos = (u_char *) data;
>    b->last = b->pos + data_size - 1;
>    b->memory = 1;    /* this buffer is in memory */
>    b->last_buf = 1;  /* this is the last buffer in the buffer chain */
>

Setting b->last_buf to 1 means the current buf is the last buf in the
whole response body stream in this context (actually it is the
indicator for the end of the output data stream). So you must not set
this for every single buf.

Also, you should never set this flag in case you're in a subrequest or
things will break.

>
> this function I am calling everytime I am receiving data (1024) from the
> backend
> when it is end of stream I am calling
> ngx_http_finalize_request(r, rc);
>

Call ngx_http_send_header once and call ngx_http_output_filter
multiple times (as needed).

If you need strict non-buffered output behaivor, you have to *wait*
for the downstream to flush out *all* the data before continuing
reading data from upstream. You can check out how the
ngx_http_upstream (in non-buffered mode) and ngx_lua modules do this.

>
> I didn't follow the lua module yet, but will look into it
>

I strongly recommend it because it should save you a *lot* of time (I guess) :)

> Is there anything I am doing wrong while setting the output buffer, do I
> need to change this line b->last_buf = 1;
> or something else.
>

See above.

Regards,
-agentzh

P.S. C programming is hard; let's go scripting! :D

_______________________________________________
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx
Hi,

I am trying to understand lua module.
Using the above script in the conf file I am able to connect to my upstream.
I have few questions regarding the Lua module.

1)How I can send some data i.e I have to send a message to my backend
probably which is more than a simple string. I have to construct it and
encode it. Probably I need to add to the c function I can see
ngx_http_lua_socket_tcp_send is used to send data over Nginx Socket, but I
could not figure out how I can modify this function and which buffers I need
to put my own data.

2)Before sock:receive I need to decrypt the data before sending to the
client. I think I can decode in the print function in lua_output.c where I
receive the data from upstream. Is that correct.


Thanks,
Raul

Raul


--
View this message in context: http://nginx.2469901.n2.nabble.com/Video-Streaming-using-non-http-backend-Ref-ngx-drizzle-tp7580235p7580380.html
Sent from the nginx mailing list archive at Nabble.com.

_______________________________________________
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx
Hello!

On Tue, Jun 12, 2012 at 3:01 PM, sammy_raul <[email protected]> wrote:
> I am trying to understand lua module.
> Using the above script in the conf file I am able to connect to my upstream.
> I have few questions regarding the Lua module.
>
> 1)How I can send some data i.e I have to send a message to my backend
> probably which is more than a simple string. I have to construct it and
> encode it. Probably I need to add to the c function I can see
> ngx_http_lua_socket_tcp_send is used to send data over Nginx Socket, but I
> could not figure out how I can modify this function and which buffers I need
> to put my own data.
>
> 2)Before sock:receive I need to decrypt the data before sending to the
> client. I think I can decode in the print function in lua_output.c where I
> receive the data from upstream. Is that correct.
>

You can just try doing encrypting and decrypting on the Lua level.
It's a scripting language anyway and you're free to use the classic
Lua/C API or LuaJIT FFI to extend your Lua script with C code if
desired.

It's not recommended, however, to patch ngx_lua cosocket's C
implementation directly.

Regards,
-agentzh

_______________________________________________
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx
Sorry, only registered users may post in this forum.

Click here to login