Video Streaming using non http backend, Ref ngx_drizzle

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Video Streaming using non http backend, Ref ngx_drizzle

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
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: Video Streaming using non http backend, Ref ngx_drizzle

sammy_raul
Anything on this, just a small hint on how I can configure the output filter would be highly appreciated.

Thanks,
Raul
Reply | Threaded
Open this post in threaded view
|

Re: Video Streaming using non http backend, Ref ngx_drizzle

Yichun Zhang (agentzh)
In reply to this post by sammy_raul
Hello!

On Mon, Jun 4, 2012 at 10:01 AM, Sammy Raul <[hidden email]> 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
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: Video Streaming using non http backend, Ref ngx_drizzle

sammy_raul
This post was updated on .
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. It is only sending the first 1024B i.e 1KB to the client, but looking at the print statements my above function is getting called everytime I receive data from backend.

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
Reply | Threaded
Open this post in threaded view
|

Re: Video Streaming using non http backend, Ref ngx_drizzle

Yichun Zhang (agentzh)
Hello!

On Tue, Jun 5, 2012 at 12:06 PM, sammy_raul <[hidden email]> 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
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: Video Streaming using non http backend, Ref ngx_drizzle

sammy_raul
In reply to this post by Yichun Zhang (agentzh)
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
 
Reply | Threaded
Open this post in threaded view
|

Re: Video Streaming using non http backend, Ref ngx_drizzle

Yichun Zhang (agentzh)
Hello!

On Tue, Jun 12, 2012 at 3:01 PM, sammy_raul <[hidden email]> 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
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx