http streaming with nginx module

Pete1103 nginx-forum at forum.nginx.org
Tue Jan 29 05:37:59 UTC 2019


Hello all,

I tried to make a third-party module in nginx in order to support the ts
stream in shared_memory. However, in my nginx handler function, it will
output a FILE_SIZE ts steam in once. I want to enable "Transfer Encoding:
chunked" in this function, so it can continuously send data to a client over
a single HTTP connection that remains open indefinitely. Does the function "
ngx_http_output_filter(r, &out)" can achieve this goal? or I should  use
another function to make it?

nginx version: 1.15.7
here is my  nginx handler code:
static ngx_int_t ngx_http_ts_handler(ngx_http_request_t *r){
    
    ngx_int_t  rc;
    ngx_buf_t *b;
    ngx_chain_t out;
    char uri[50] = {0};
    static char ngx_ts_data[FILE_SIZE] = {0};

    if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_PUT ))) {
        return NGX_HTTP_NOT_ALLOWED;
    }
    
    rc = ngx_http_discard_request_body(r);
    if (rc != NGX_OK) return rc;

     /* Set the Content-Type header. "text/html" */ 
    r->headers_out.content_type.len = sizeof(TS_TYPE) - 1;
    r->headers_out.content_type.data = (u_char *) TS_TYPE;
    /* Allocate a new buffer for sending out the reply. */
    b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
    /* Insertion in the buffer chain. */
    out.buf = b;
    out.next = NULL;
    memcpy(&uri, r-> uri_start , r-> uri_end-(r-> uri_start));
     /*make http header*/
    if (!strncmp(uri, "/VideoInput/", 12)){

        int shm_fd;
        uint32_t *pos_hdr;
        int pos;
        int cur_loc;
        char *fifo_start;
        int remain = 0;
    
        shm_fd = open_output_shm(SHM_NAME);
        g_shm_ptr = (char *)mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED, shm_fd, 0);
        close(shm_fd);

        pos_hdr = (uint32_t *)g_shm_ptr;
        //chn = (int)(*pos_hdr & CHN_MASK);
        pos = (int)(*pos_hdr & POS_MASK);

        if (pos > (PACKET_SIZE * 100)) {
            cur_loc = pos - (PACKET_SIZE * 100);
        } else cur_loc = 0;

        fifo_start = (char *)(pos_hdr + 1);
        if (fifo_start[cur_loc] != 0x47) {
            //json_object_set_new(jret, "TS", json_string("non-sync"));
            memset(ngx_ts_data, 0, strlen(ngx_ts_data));
            memcpy(ngx_ts_data,"TS non-sync", 11);
            b->pos = (u_char *)ngx_ts_data;
            b->last = (u_char *)ngx_ts_data + strlen(ngx_ts_data); 
        }else{

            if( pos > FILE_SIZE ){

                b->pos = (u_char *)(g_shm_ptr + 4); 
                b->last = (u_char *)(g_shm_ptr + 4) + FILE_SIZE; 
               
            }else{

                remain = FILE_SIZE - pos;
                memset(ngx_ts_data, 0, sizeof(ngx_ts_data)-1);
                memcpy(ngx_ts_data, g_shm_ptr + (SHM_SIZE - remain),
remain);
                memcpy(&ngx_ts_data[remain], g_shm_ptr + 4, pos);
                b->pos = (u_char *)ngx_ts_data; 
                b->last = (u_char *)ngx_ts_data + sizeof(ngx_ts_data)-1;
            }
        }
                                 
    }else{
        //json_object_set_new(jret, "TS", json_string("Nothing"));
        memset(ngx_ts_data, 0, strlen(ngx_ts_data));
        memcpy(ngx_ts_data,"No",2);
        b->pos = (u_char *)ngx_ts_data; 
        b->last = (u_char *)ngx_ts_data + strlen(ngx_ts_data);
    }
      
    b->memory = 1; /* content is in read-only memory */
     /* there will be no more buffers in the request */
    b->last_buf = 1;
    /* Sending the headers for the reply. */
    r->headers_out.status = NGX_HTTP_OK; /* 200 status code */
    rc = ngx_http_send_header(r); /* Send the headers */

    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
            return rc;
        }
    /* Send the body, and return the status code of the output filter chain.
*/
    return ngx_http_output_filter(r, &out);
}

Any help would be appreciated,

Pete

Posted at Nginx Forum: https://forum.nginx.org/read.php?2,282849,282849#msg-282849



More information about the nginx mailing list