# Video Streaming using non http backend, Ref ngx\_drizzle

**URL:** <https://www.ruby-forum.com/t/video-streaming-using-non-http-backend-ref-ngx-drizzle/220249>\
**Category:** NGINX\
**Created:** [June 4, 2012, 4:02am UTC](https://www.ruby-forum.com/t/video-streaming-using-non-http-backend-ref-ngx-drizzle/220249 "2012-06-04T04:02:10Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![aris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/258eb7/32.png) [@aris](https://www.ruby-forum.com/u/aris)\
**Post date:** [June 4, 2012, 4:02am UTC](https://www.ruby-forum.com/t/video-streaming-using-non-http-backend-ref-ngx-drizzle/220249/1 "2012-06-04T04:02:10Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Sammy\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac91a4/32.png) [@Sammy\_R](https://www.ruby-forum.com/u/Sammy_R)\
**Post date:** [June 4, 2012, 10:16am UTC](https://www.ruby-forum.com/t/video-streaming-using-non-http-backend-ref-ngx-drizzle/220249/2 "2012-06-04T10:16:07Z")

</div>

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](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](http://Nabble.com).

---

<div class="post-metadata">

**Author:** ![Sammy\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac91a4/32.png) [@Sammy\_R](https://www.ruby-forum.com/u/Sammy_R)\
**Post date:** [June 4, 2012, 4:13pm UTC](https://www.ruby-forum.com/t/video-streaming-using-non-http-backend-ref-ngx-drizzle/220249/3 "2012-06-04T16:13:45Z")

</div>

Hello!

On Mon, Jun 4, 2012 at 10:01 AM, Sammy R. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
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.

> 1. 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.

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

I do not quite follow this question.

Best regards,  
-agentzh

---

<div class="post-metadata">

**Author:** ![Sammy\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac91a4/32.png) [@Sammy\_R](https://www.ruby-forum.com/u/Sammy_R)\
**Post date:** [June 5, 2012, 6:06am UTC](https://www.ruby-forum.com/t/video-streaming-using-non-http-backend-ref-ngx-drizzle/220249/4 "2012-06-05T06:06:36Z")

</div>

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](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](http://Nabble.com).

---

<div class="post-metadata">

**Author:** ![Sammy\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac91a4/32.png) [@Sammy\_R](https://www.ruby-forum.com/u/Sammy_R)\
**Post date:** [June 5, 2012, 6:17am UTC](https://www.ruby-forum.com/t/video-streaming-using-non-http-backend-ref-ngx-drizzle/220249/5 "2012-06-05T06:17:42Z")

</div>

Hello!

On Tue, Jun 5, 2012 at 12:06 PM, sammy\_raul [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
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! 😃

---

<div class="post-metadata">

**Author:** ![Sammy\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac91a4/32.png) [@Sammy\_R](https://www.ruby-forum.com/u/Sammy_R)\
**Post date:** [June 12, 2012, 1:43pm UTC](https://www.ruby-forum.com/t/video-streaming-using-non-http-backend-ref-ngx-drizzle/220249/6 "2012-06-12T13:43:51Z")

</div>

Hello!

On Tue, Jun 12, 2012 at 3:01 PM, sammy\_raul [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> 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

---

<div class="post-metadata">

**Author:** ![Sammy\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ac91a4/32.png) [@Sammy\_R](https://www.ruby-forum.com/u/Sammy_R)\
**Post date:** [June 12, 2012, 9:01am UTC](https://www.ruby-forum.com/t/video-streaming-using-non-http-backend-ref-ngx-drizzle/220249/7 "2012-06-12T09:01:35Z")

</div>

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](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](http://Nabble.com).
