├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE.md ├── workflows │ └── nginx-http-flv-module.yml ├── CONTRIBUTING.md └── CODE_OF_CONDUCT.md ├── test ├── dump.sh ├── play.sh ├── www │ ├── bg.jpg │ ├── jwplayer_old │ │ ├── player.swf │ │ └── swfobject.js │ ├── jwplayer │ │ └── jwplayer.flash.swf │ ├── index.html │ └── record.html ├── ffstream.sh ├── rtmp-publisher │ ├── RtmpPlayer.swf │ ├── RtmpPublisher.swf │ ├── RtmpPlayerLight.swf │ ├── README.md │ ├── publisher.html │ ├── player.html │ ├── RtmpPlayer.mxml │ ├── RtmpPublisher.mxml │ ├── RtmpPlayerLight.mxml │ └── swfobject.js ├── README.md └── nginx.conf ├── samples ├── flv.js.png └── jwplayer_vlc.png ├── doc └── README.md ├── hls ├── ngx_rtmp_hls_module.h ├── ngx_rtmp_mpegts.h ├── ngx_rtmp_mpegts_crc.h ├── ngx_rtmp_mpegts_crc.c └── ngx_rtmp_mpegts.c ├── ngx_rtmp_version.h ├── ngx_rtmp_proxy_protocol.h ├── ngx_rtmp_streams.h ├── ngx_rtmp_bandwidth.c ├── ngx_rtmp_bandwidth.h ├── ngx_rtmp_eval.h ├── AUTHORS ├── ngx_rtmp_bitop.c ├── ngx_rtmp_bitop.h ├── ngx_rtmp_flv_live_index_module.c ├── dash └── ngx_rtmp_mp4.h ├── LICENSE ├── ngx_rtmp_gop_cache_module.h ├── ngx_rtmp_amf.h ├── ngx_rtmp_netcall_module.h ├── ngx_http_flv_live_module.h ├── ngx_rtmp_play_module.h ├── ngx_rtmp_shared.c ├── ngx_rtmp_relay_module.h ├── ngx_rtmp_live_module.h ├── ngx_rtmp_variables.h ├── ngx_rtmp_record_module.h ├── ngx_rtmp_codec_module.h ├── ngx_rtmp_proxy_protocol.c ├── ngx_rtmp_cmd_module.h ├── ngx_rtmp_limit_module.c ├── ngx_rtmp_eval.c ├── config ├── ngx_rtmp_init.c ├── README.CN.md ├── ngx_rtmp_access_module.c ├── ngx_rtmp_receive.c └── README.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: ['https://www.paypal.me/ShingWong'] 2 | -------------------------------------------------------------------------------- /test/dump.sh: -------------------------------------------------------------------------------- 1 | rtmpdump -v -r "rtmp://localhost/myapp/mystream" 2 | -------------------------------------------------------------------------------- /test/play.sh: -------------------------------------------------------------------------------- 1 | ffplay -loglevel verbose "rtmp://localhost/myapp/mystream" 2 | -------------------------------------------------------------------------------- /test/www/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KeithinX/romn/HEAD/test/www/bg.jpg -------------------------------------------------------------------------------- /samples/flv.js.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KeithinX/romn/HEAD/samples/flv.js.png -------------------------------------------------------------------------------- /samples/jwplayer_vlc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KeithinX/romn/HEAD/samples/jwplayer_vlc.png -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | Documentation is available here: 2 | https://github.com/arut/nginx-rtmp-module/wiki 3 | -------------------------------------------------------------------------------- /test/ffstream.sh: -------------------------------------------------------------------------------- 1 | ffmpeg -loglevel verbose -re -i ~/movie.avi -f flv rtmp://localhost/myapp/mystream 2 | -------------------------------------------------------------------------------- /test/www/jwplayer_old/player.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KeithinX/romn/HEAD/test/www/jwplayer_old/player.swf -------------------------------------------------------------------------------- /test/rtmp-publisher/RtmpPlayer.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KeithinX/romn/HEAD/test/rtmp-publisher/RtmpPlayer.swf -------------------------------------------------------------------------------- /test/rtmp-publisher/RtmpPublisher.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KeithinX/romn/HEAD/test/rtmp-publisher/RtmpPublisher.swf -------------------------------------------------------------------------------- /test/www/jwplayer/jwplayer.flash.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KeithinX/romn/HEAD/test/www/jwplayer/jwplayer.flash.swf -------------------------------------------------------------------------------- /test/rtmp-publisher/RtmpPlayerLight.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KeithinX/romn/HEAD/test/rtmp-publisher/RtmpPlayerLight.swf -------------------------------------------------------------------------------- /hls/ngx_rtmp_hls_module.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Winshining 4 | */ 5 | 6 | 7 | #ifndef _NGX_RTMP_HLS_MODULE_H_ 8 | #define _NGX_RTMP_HLS_MODULE_H_ 9 | 10 | 11 | ngx_int_t ngx_rtmp_hls_copy(ngx_rtmp_session_t *s, void *dst, u_char **src, 12 | size_t n, ngx_chain_t **in); 13 | 14 | 15 | #endif /* _NGX_RTMP_HLS_MODULE_H_ */ 16 | -------------------------------------------------------------------------------- /ngx_rtmp_version.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | * Copyright (C) Winshining 5 | */ 6 | 7 | 8 | #ifndef _NGX_RTMP_VERSION_H_INCLUDED_ 9 | #define _NGX_RTMP_VERSION_H_INCLUDED_ 10 | 11 | 12 | #define nginx_rtmp_version 1002011 13 | #define NGINX_RTMP_VERSION "1.2.11" 14 | 15 | 16 | #endif /* _NGX_RTMP_VERSION_H_INCLUDED_ */ 17 | -------------------------------------------------------------------------------- /test/rtmp-publisher/README.md: -------------------------------------------------------------------------------- 1 | # RTMP Publisher 2 | 3 | Simple RTMP publisher. 4 | 5 | Edit the following flashvars in publisher.html & player.html to suite your needs. 6 | 7 | streamer: RTMP endpoint 8 | file: live stream name 9 | 10 | ## Compile 11 | 12 | Install flex sdk http://www.adobe.com/devnet/flex/flex-sdk-download.html 13 | 14 | mxmlc RtmpPublisher.mxml 15 | mxmlc RtmpPlayer.mxml 16 | -------------------------------------------------------------------------------- /ngx_rtmp_proxy_protocol.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | */ 5 | 6 | 7 | #ifndef _NGX_RTMP_PROXY_PROTOCOL_H_INCLUDED_ 8 | #define _NGX_RTMP_PROXY_PROTOCOL_H_INCLUDED_ 9 | 10 | 11 | #include 12 | #include 13 | #include "ngx_rtmp.h" 14 | 15 | 16 | void ngx_rtmp_proxy_protocol(ngx_rtmp_session_t *c); 17 | 18 | 19 | #endif /* _NGX_RTMP_PROXY_PROTOCOL_H_INCLUDED_ */ 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | When you meet a bug, please open the issue including a title prefixed by '[bug]' and describe it as follows: 2 | (当你碰到一个 bug,请在提出问题时以 '[bug]' 为前缀写明标题,并且像下面的内容一样描述它): 3 | 4 | ### Expected behavior (期望行为) 5 | 6 | ### Actual behavior (实际行为) 7 | 8 | ### OS and Nginx version (操作系统和 Nginx 版本号) 9 | 10 | ### Configuration file (配置文件) 11 | 12 | ### Steps to reproduce the behavior (复现问题步骤) 13 | 14 | ### Error log if any (错误日志) 15 | -------------------------------------------------------------------------------- /ngx_rtmp_streams.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | */ 5 | 6 | 7 | #ifndef _NGX_RTMP_STREAMS_H_INCLUDED_ 8 | #define _NGX_RTMP_STREAMS_H_INCLUDED_ 9 | 10 | 11 | #define NGX_RTMP_MSID 1 12 | 13 | #define NGX_RTMP_CSID_AMF_INI 3 14 | #define NGX_RTMP_CSID_AMF 5 15 | #define NGX_RTMP_CSID_AUDIO 6 16 | #define NGX_RTMP_CSID_VIDEO 7 17 | 18 | 19 | #endif /* _NGX_RTMP_STREAMS_H_INCLUDED_ */ 20 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | # RTMP tests 2 | 3 | nginx.conf is sample config for testing nginx-rtmp. 4 | Please update paths in it before using. 5 | 6 | RTMP port: 1935, HTTP port: 8080 7 | 8 | * http://localhost:8080/ - play myapp/mystream with JWPlayer 9 | * http://localhost:8080/record.html - capture myapp/mystream from webcam with old JWPlayer 10 | * http://localhost:8080/rtmp-publisher/player.html - play myapp/mystream with the test flash applet 11 | * http://localhost:8080/rtmp-publisher/publisher.html - capture myapp/mystream with the test flash applet 12 | -------------------------------------------------------------------------------- /test/www/index.html: -------------------------------------------------------------------------------- 1 | Play | Record 2 |
3 | 4 | 5 |
Loading the player ...
6 | 20 | -------------------------------------------------------------------------------- /test/rtmp-publisher/publisher.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | RTMP Publisher 5 | 6 | 13 | 14 | 15 |
16 |

Flash not installed

17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /ngx_rtmp_bandwidth.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | */ 5 | 6 | 7 | #include 8 | #include 9 | #include "ngx_rtmp_bandwidth.h" 10 | 11 | 12 | void 13 | ngx_rtmp_update_bandwidth(ngx_rtmp_bandwidth_t *bw, uint32_t bytes) 14 | { 15 | if (ngx_cached_time->sec > bw->intl_end) { 16 | bw->bandwidth = ngx_cached_time->sec > 17 | bw->intl_end + NGX_RTMP_BANDWIDTH_INTERVAL 18 | ? 0 19 | : bw->intl_bytes / NGX_RTMP_BANDWIDTH_INTERVAL; 20 | bw->intl_bytes = 0; 21 | bw->intl_end = ngx_cached_time->sec + NGX_RTMP_BANDWIDTH_INTERVAL; 22 | } 23 | 24 | bw->bytes += bytes; 25 | bw->intl_bytes += bytes; 26 | } 27 | -------------------------------------------------------------------------------- /test/rtmp-publisher/player.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | RTMP Player 5 | 6 | 16 | 17 | 18 |
19 |

Flash not installed

20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /ngx_rtmp_bandwidth.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | */ 5 | 6 | 7 | #ifndef _NGX_RTMP_BANDWIDTH_H_INCLUDED_ 8 | #define _NGX_RTMP_BANDWIDTH_H_INCLUDED_ 9 | 10 | 11 | #include 12 | #include 13 | 14 | 15 | /* Bandwidth update interval in seconds */ 16 | #define NGX_RTMP_BANDWIDTH_INTERVAL 10 17 | 18 | 19 | typedef struct { 20 | uint64_t bytes; 21 | uint64_t bandwidth; /* bytes/sec */ 22 | 23 | time_t intl_end; 24 | uint64_t intl_bytes; 25 | } ngx_rtmp_bandwidth_t; 26 | 27 | 28 | void ngx_rtmp_update_bandwidth(ngx_rtmp_bandwidth_t *bw, uint32_t bytes); 29 | 30 | 31 | #endif /* _NGX_RTMP_BANDWIDTH_H_INCLUDED_ */ 32 | -------------------------------------------------------------------------------- /ngx_rtmp_eval.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | */ 5 | 6 | 7 | #ifndef _NGX_RTMP_EVAL_H_INCLUDED_ 8 | #define _NGX_RTMP_EVAL_H_INCLUDED_ 9 | 10 | 11 | #include 12 | #include 13 | #include "ngx_rtmp.h" 14 | 15 | 16 | typedef struct ngx_rtmp_eval_s ngx_rtmp_eval_t; 17 | 18 | 19 | typedef void (* ngx_rtmp_eval_pt)(void *ctx, ngx_rtmp_eval_t *e, 20 | ngx_str_t *ret); 21 | 22 | 23 | struct ngx_rtmp_eval_s { 24 | ngx_str_t name; 25 | ngx_rtmp_eval_pt handler; 26 | ngx_uint_t offset; 27 | }; 28 | 29 | 30 | #define ngx_rtmp_null_eval { ngx_null_string, NULL, 0 } 31 | 32 | 33 | /* standard session eval variables */ 34 | extern ngx_rtmp_eval_t ngx_rtmp_eval_session[]; 35 | 36 | 37 | ngx_int_t ngx_rtmp_eval(void *ctx, ngx_str_t *in, ngx_rtmp_eval_t **e, 38 | ngx_str_t *out, ngx_log_t *log); 39 | 40 | 41 | ngx_int_t ngx_rtmp_eval_streams(ngx_str_t *in); 42 | 43 | 44 | #endif /* _NGX_RTMP_EVAL_H_INCLUDED_ */ 45 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Project author: 2 | 3 | Roman Arutyunyan 4 | Moscow, Russia 5 | Contacts: 6 | arut@qip.ru 7 | arutyunyan.roman@gmail.com 8 | 9 | Winshining 10 | Beijing, China 11 | Contacts: 12 | winshining@163.com 13 | 14 | Gnolizuh 15 | Beijing, China 16 | Contacts: 17 | huzilong_007@163.com 18 | huzilong@kingsoft.com 19 | 20 | han4235 21 | Suzhou, China 22 | Contacts: 23 | https://github.com/han4235 24 | 25 | plainheart 26 | Zhengzhou, China 27 | Contacts: 28 | https://github.com/plainheart 29 | 30 | HeyJupiter: 31 | Seattle, US 32 | Contacts: 33 | https://github.com/HeyJupiter 34 | 35 | Vladimir Vainer 36 | - 37 | Contacts: 38 | https://github.com/ferreus 39 | 40 | ever4Keny 41 | China 42 | Contacts: 43 | https://github.com/ever4Keny 44 | 45 | spacewander 46 | Guangzhou, China 47 | Contacts: 48 | spacewanderlzx@gmail.com 49 | 50 | ham3r 51 | - 52 | Contacts: 53 | https://github.com/ham3r 54 | 55 | deamos 56 | Scranton, PA 57 | Contacts: 58 | https://github.com/deamos 59 | 60 | vacing 61 | Shenzhen, China 62 | Contacts: 63 | https://github.com/vacing 64 | -------------------------------------------------------------------------------- /hls/ngx_rtmp_mpegts.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | * Copyright (C) Winshining 5 | */ 6 | 7 | 8 | #ifndef _NGX_RTMP_MPEGTS_H_INCLUDED_ 9 | #define _NGX_RTMP_MPEGTS_H_INCLUDED_ 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | #include "ngx_rtmp_codec_module.h" 16 | 17 | 18 | typedef struct { 19 | ngx_fd_t fd; 20 | ngx_log_t *log; 21 | unsigned encrypt:1; 22 | unsigned size:4; 23 | u_char buf[16]; 24 | u_char iv[16]; 25 | AES_KEY key; 26 | } ngx_rtmp_mpegts_file_t; 27 | 28 | 29 | typedef struct { 30 | uint64_t pts; 31 | uint64_t dts; 32 | ngx_uint_t pid; 33 | ngx_uint_t sid; 34 | ngx_uint_t cc; 35 | unsigned key:1; 36 | } ngx_rtmp_mpegts_frame_t; 37 | 38 | 39 | ngx_int_t ngx_rtmp_mpegts_init_encryption(ngx_rtmp_mpegts_file_t *file, 40 | u_char *key, size_t key_len, uint64_t iv); 41 | ngx_int_t ngx_rtmp_mpegts_open_file(ngx_rtmp_mpegts_file_t *file, u_char *path, 42 | ngx_rtmp_codec_ctx_t *codec_ctx, ngx_uint_t counter, ngx_log_t *log); 43 | ngx_int_t ngx_rtmp_mpegts_close_file(ngx_rtmp_mpegts_file_t *file); 44 | ngx_int_t ngx_rtmp_mpegts_write_frame(ngx_rtmp_mpegts_file_t *file, 45 | ngx_rtmp_mpegts_frame_t *f, ngx_buf_t *b); 46 | 47 | 48 | #endif /* _NGX_RTMP_MPEGTS_H_INCLUDED_ */ 49 | -------------------------------------------------------------------------------- /ngx_rtmp_bitop.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | */ 5 | 6 | 7 | #include 8 | #include 9 | #include "ngx_rtmp_bitop.h" 10 | 11 | 12 | void 13 | ngx_rtmp_bit_init_reader(ngx_rtmp_bit_reader_t *br, u_char *pos, u_char *last) 14 | { 15 | ngx_memzero(br, sizeof(ngx_rtmp_bit_reader_t)); 16 | 17 | br->pos = pos; 18 | br->last = last; 19 | } 20 | 21 | 22 | uint64_t 23 | ngx_rtmp_bit_read(ngx_rtmp_bit_reader_t *br, ngx_uint_t n) 24 | { 25 | uint64_t v; 26 | ngx_uint_t d; 27 | 28 | v = 0; 29 | 30 | while (n) { 31 | 32 | if (br->pos >= br->last) { 33 | br->err = 1; 34 | return 0; 35 | } 36 | 37 | d = (br->offs + n > 8 ? (ngx_uint_t) (8 - br->offs) : n); 38 | 39 | v <<= d; 40 | v += (*br->pos >> (8 - br->offs - d)) & ((u_char) 0xff >> (8 - d)); 41 | 42 | br->offs += d; 43 | n -= d; 44 | 45 | if (br->offs == 8) { 46 | br->pos++; 47 | br->offs = 0; 48 | } 49 | } 50 | 51 | return v; 52 | } 53 | 54 | 55 | uint64_t 56 | ngx_rtmp_bit_read_golomb(ngx_rtmp_bit_reader_t *br) 57 | { 58 | ngx_uint_t n; 59 | 60 | for (n = 0; ngx_rtmp_bit_read(br, 1) == 0 && !br->err; n++); 61 | 62 | return ((uint64_t) 1 << n) + ngx_rtmp_bit_read(br, n) - 1; 63 | } 64 | -------------------------------------------------------------------------------- /.github/workflows/nginx-http-flv-module.yml: -------------------------------------------------------------------------------- 1 | name: nginx-http-flv-module CI 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | env: 15 | NGINX_VERSION: nginx-1.22.1 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | - name: download nginx 20 | working-directory: ../ 21 | run: wget https://nginx.org/download/${{env.NGINX_VERSION}}.tar.gz 22 | - name: uncompress nginx 23 | working-directory: ../ 24 | run: tar zxvf ${{env.NGINX_VERSION}}.tar.gz 25 | - name: configure (build into nginx) 26 | working-directory: ../${{env.NGINX_VERSION}} 27 | run: ./configure --add-module=../nginx-http-flv-module 28 | - name: make 29 | working-directory: ../${{env.NGINX_VERSION}} 30 | run: make 31 | - name: clean 32 | working-directory: ../${{env.NGINX_VERSION}} 33 | run: make clean 34 | - name: configure (build as a dynamic module) 35 | working-directory: ../${{env.NGINX_VERSION}} 36 | run: ./configure --add-dynamic-module=../nginx-http-flv-module 37 | - name: make 38 | working-directory: ../${{env.NGINX_VERSION}} 39 | run: make 40 | - name: remove 41 | working-directory: ../ 42 | run: rm -rf "${{env.NGINX_VERSION}}*" 43 | -------------------------------------------------------------------------------- /ngx_rtmp_bitop.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | */ 5 | 6 | 7 | #ifndef _NGX_RTMP_BITOP_H_INCLUDED_ 8 | #define _NGX_RTMP_BITOP_H_INCLUDED_ 9 | 10 | 11 | #include 12 | #include 13 | 14 | 15 | typedef struct { 16 | u_char *pos; 17 | u_char *last; 18 | ngx_uint_t offs; 19 | ngx_uint_t err; 20 | } ngx_rtmp_bit_reader_t; 21 | 22 | 23 | void ngx_rtmp_bit_init_reader(ngx_rtmp_bit_reader_t *br, u_char *pos, 24 | u_char *last); 25 | uint64_t ngx_rtmp_bit_read(ngx_rtmp_bit_reader_t *br, ngx_uint_t n); 26 | uint64_t ngx_rtmp_bit_read_golomb(ngx_rtmp_bit_reader_t *br); 27 | 28 | 29 | #define ngx_rtmp_bit_read_err(br) ((br)->err) 30 | 31 | #define ngx_rtmp_bit_read_eof(br) ((br)->pos == (br)->last) 32 | 33 | #define ngx_rtmp_bit_read_8(br) \ 34 | ((uint8_t) ngx_rtmp_bit_read(br, 8)) 35 | 36 | #define ngx_rtmp_bit_read_16(br) \ 37 | ((uint16_t) ngx_rtmp_bit_read(br, 16)) 38 | 39 | #define ngx_rtmp_bit_read_32(br) \ 40 | ((uint32_t) ngx_rtmp_bit_read(br, 32)) 41 | 42 | #define ngx_rtmp_bit_read_64(br) \ 43 | ((uint64_t) ngx_rtmp_bit_read(br, 64)) 44 | 45 | 46 | #endif /* _NGX_RTMP_BITOP_H_INCLUDED_ */ 47 | -------------------------------------------------------------------------------- /ngx_rtmp_flv_live_index_module.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Winshining 4 | */ 5 | 6 | #include 7 | #include 8 | #include "ngx_http_flv_live_module.h" 9 | 10 | 11 | static ngx_rtmp_play_pt next_play; 12 | static ngx_rtmp_close_stream_pt next_close_stream; 13 | 14 | 15 | static ngx_int_t ngx_rtmp_flv_live_index_postconfiguration(ngx_conf_t *cf); 16 | 17 | 18 | static ngx_rtmp_module_t ngx_rtmp_flv_live_module_ctx = { 19 | NULL, 20 | ngx_rtmp_flv_live_index_postconfiguration, /* postconfiguration */ 21 | NULL, 22 | NULL, 23 | NULL, 24 | NULL, 25 | NULL, 26 | NULL 27 | }; 28 | 29 | 30 | static ngx_command_t ngx_rtmp_flv_live_index_commands[] = { 31 | ngx_null_command 32 | }; 33 | 34 | 35 | ngx_module_t ngx_rtmp_flv_live_index_module = { 36 | NGX_MODULE_V1, 37 | &ngx_rtmp_flv_live_module_ctx, 38 | ngx_rtmp_flv_live_index_commands, 39 | NGX_RTMP_MODULE, 40 | NULL, 41 | NULL, 42 | NULL, 43 | NULL, 44 | NULL, 45 | NULL, 46 | NULL, 47 | NGX_MODULE_V1_PADDING 48 | }; 49 | 50 | 51 | static ngx_int_t 52 | ngx_rtmp_flv_live_index_postconfiguration(ngx_conf_t *cf) 53 | { 54 | next_play = ngx_rtmp_play; 55 | ngx_rtmp_play = ngx_http_flv_live_play; 56 | 57 | next_close_stream = ngx_rtmp_close_stream; 58 | ngx_rtmp_close_stream = ngx_http_flv_live_close_stream; 59 | 60 | http_flv_live_next_play = next_play; 61 | http_flv_live_next_close_stream = next_close_stream; 62 | 63 | return NGX_OK; 64 | } 65 | 66 | -------------------------------------------------------------------------------- /test/nginx.conf: -------------------------------------------------------------------------------- 1 | worker_processes 1; 2 | 3 | error_log logs/error.log debug; 4 | 5 | events { 6 | worker_connections 1024; 7 | } 8 | 9 | rtmp { 10 | server { 11 | listen 1935; 12 | 13 | application myapp { 14 | live on; 15 | 16 | #record keyframes; 17 | #record_path /tmp; 18 | #record_max_size 128K; 19 | #record_interval 30s; 20 | #record_suffix .this.is.flv; 21 | 22 | #on_publish http://localhost:8080/publish; 23 | #on_play http://localhost:8080/play; 24 | #on_record_done http://localhost:8080/record_done; 25 | } 26 | } 27 | } 28 | 29 | http { 30 | server { 31 | listen 8080; 32 | 33 | location /stat { 34 | rtmp_stat all; 35 | rtmp_stat_stylesheet stat.xsl; 36 | } 37 | 38 | location /stat.xsl { 39 | root /path/to/nginx-rtmp-module/; 40 | } 41 | 42 | location /control { 43 | rtmp_control all; 44 | } 45 | 46 | #location /publish { 47 | # return 201; 48 | #} 49 | 50 | #location /play { 51 | # return 202; 52 | #} 53 | 54 | #location /record_done { 55 | # return 203; 56 | #} 57 | 58 | location /rtmp-publisher { 59 | root /path/to/nginx-rtmp-module/test; 60 | } 61 | 62 | location / { 63 | root /path/to/nginx-rtmp-module/test/www; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /dash/ngx_rtmp_mp4.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef _NGX_RTMP_MP4_H_INCLUDED_ 4 | #define _NGX_RTMP_MP4_H_INCLUDED_ 5 | 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | #define NGX_RTMP_MP4_SAMPLE_SIZE 0x01 13 | #define NGX_RTMP_MP4_SAMPLE_DURATION 0x02 14 | #define NGX_RTMP_MP4_SAMPLE_DELAY 0x04 15 | #define NGX_RTMP_MP4_SAMPLE_KEY 0x08 16 | 17 | 18 | typedef struct { 19 | uint32_t size; 20 | uint32_t duration; 21 | uint32_t delay; 22 | uint32_t timestamp; 23 | unsigned key:1; 24 | } ngx_rtmp_mp4_sample_t; 25 | 26 | 27 | typedef enum { 28 | NGX_RTMP_MP4_FILETYPE_INIT, 29 | NGX_RTMP_MP4_FILETYPE_SEG 30 | } ngx_rtmp_mp4_file_type_t; 31 | 32 | 33 | typedef enum { 34 | NGX_RTMP_MP4_VIDEO_TRACK, 35 | NGX_RTMP_MP4_AUDIO_TRACK 36 | } ngx_rtmp_mp4_track_type_t; 37 | 38 | 39 | ngx_int_t ngx_rtmp_mp4_write_ftyp(ngx_buf_t *b); 40 | ngx_int_t ngx_rtmp_mp4_write_styp(ngx_buf_t *b); 41 | ngx_int_t ngx_rtmp_mp4_write_moov(ngx_rtmp_session_t *s, ngx_buf_t *b, 42 | ngx_rtmp_mp4_track_type_t ttype); 43 | ngx_int_t ngx_rtmp_mp4_write_moof(ngx_buf_t *b, uint32_t earliest_pres_time, 44 | uint32_t sample_count, ngx_rtmp_mp4_sample_t *samples, 45 | ngx_uint_t sample_mask, uint32_t index); 46 | ngx_int_t ngx_rtmp_mp4_write_sidx(ngx_buf_t *b, 47 | ngx_uint_t reference_size, uint32_t earliest_pres_time, 48 | uint32_t latest_pres_time); 49 | ngx_uint_t ngx_rtmp_mp4_write_mdat(ngx_buf_t *b, ngx_uint_t size); 50 | 51 | 52 | #endif /* _NGX_RTMP_MP4_H_INCLUDED_ */ 53 | -------------------------------------------------------------------------------- /test/www/record.html: -------------------------------------------------------------------------------- 1 | Play | Record 2 |
3 | 4 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2012-2017, Roman Arutyunyan 4 | Copyright (c) 2017-2024, Winshining 5 | Copyright (c) 2018, han4235, Vladimir Vainer 6 | Copyright (c) 2018-2019, plainheart, HeyJupiter 7 | Copyright (c) 2019, ever4Keny 8 | Copyright (c) 2020, spacewander, ham3r 9 | Copyright (c) 2022, deamons 10 | Copyright (c) 2024, vacing 11 | All rights reserved. 12 | 13 | Redistribution and use in source and binary forms, with or without 14 | modification, are permitted provided that the following conditions are met: 15 | 16 | * Redistributions of source code must retain the above copyright notice, this 17 | list of conditions and the following disclaimer. 18 | 19 | * Redistributions in binary form must reproduce the above copyright notice, 20 | this list of conditions and the following disclaimer in the documentation 21 | and/or other materials provided with the distribution. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 24 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 27 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | -------------------------------------------------------------------------------- /ngx_rtmp_gop_cache_module.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Gnolizuh 4 | * Copyright (C) Winshining 5 | */ 6 | 7 | #ifndef _NGX_RTMP_GOP_CACHE_H_INCLUDE_ 8 | #define _NGX_RTMP_GOP_CACHE_H_INCLUDE_ 9 | 10 | 11 | #define NGX_GOP_CACHE_POOL_CREATE_SIZE 4096 12 | 13 | 14 | typedef struct ngx_rtmp_gop_frame_s ngx_rtmp_gop_frame_t; 15 | typedef struct ngx_rtmp_gop_cache_s ngx_rtmp_gop_cache_t; 16 | 17 | 18 | struct ngx_rtmp_gop_frame_s { 19 | ngx_rtmp_header_t h; 20 | ngx_uint_t prio; 21 | ngx_chain_t *frame; 22 | ngx_rtmp_gop_frame_t *next; 23 | }; 24 | 25 | 26 | struct ngx_rtmp_gop_cache_s { 27 | ngx_rtmp_gop_frame_t *frame_head; 28 | ngx_rtmp_gop_frame_t *frame_tail; 29 | ngx_rtmp_gop_cache_t *next; 30 | 31 | ngx_chain_t *video_seq_header; 32 | ngx_chain_t *audio_seq_header; 33 | ngx_chain_t *meta; 34 | 35 | ngx_uint_t meta_version; 36 | 37 | ngx_int_t video_frame_in_this; 38 | ngx_int_t audio_frame_in_this; 39 | }; 40 | 41 | 42 | typedef struct ngx_rtmp_gop_cache_app_conf_s { 43 | ngx_flag_t gop_cache; 44 | size_t gop_cache_count; 45 | size_t gop_max_frame_count; 46 | size_t gop_max_video_count; 47 | size_t gop_max_audio_count; 48 | } ngx_rtmp_gop_cache_app_conf_t; 49 | 50 | 51 | typedef struct ngx_rtmp_gop_cache_ctx_s { 52 | ngx_pool_t *pool; 53 | ngx_rtmp_gop_cache_t *cache_head; 54 | ngx_rtmp_gop_cache_t *cache_tail; 55 | ngx_rtmp_gop_cache_t *free_cache; 56 | ngx_rtmp_gop_frame_t *free_frame; 57 | 58 | size_t gop_cache_count; 59 | size_t video_frame_in_all; 60 | size_t audio_frame_in_all; 61 | } ngx_rtmp_gop_cache_ctx_t; 62 | 63 | 64 | #endif 65 | 66 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Guidelines to contribute 2 | 3 | #### **When you find a bug** 4 | 5 | * **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/winshining/nginx-http-flv-module/issues). 6 | 7 | * If there is no issue addressing the problem, [open a new one](https://github.com/winshining/nginx-http-flv-module/issues/new). Be sure to include a **title prefixed by '[bug]' and clear description**, as much relevant information as possible, and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring. 8 | 9 | #### **Write a patch that fixes a bug** 10 | 11 | * Open a new GitHub pull request with the patch. 12 | 13 | * Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable. 14 | 15 | * Before submitting, be sure the commit description is prefixed by: 16 | * **[add]** if new features were added. 17 | * **[dev]** if codes were changed. 18 | * **[fix]** if bugs were fixed. 19 | * **[misc]** if some changes were done and bugs were fixed. 20 | 21 | * Ensure that your codes conform to code conventions: 22 | * All files are prefixed by 'ngx\_'. 23 | * Include #ifndef \_FILE\_NAME\_H\_INCLUDED\_, #define \_FILE\_NAME\_H\_INCLUDED\_ and #endif in header files. 24 | * Comments use /* ... */ are preferable. 25 | * It would be better that built-in types appear before customized types. 26 | * There should be no less than 2 spaces between types and variables. 27 | * Variables are aligned by character, not '\*'. 28 | * No more than 80 characters in a single code or comment line. 29 | * Two blank lines between two functions, styles of macro and type definitions are same as functions. 30 | 31 | #### **Add a new feature or change an existing one** 32 | 33 | * Open an issue on GitHub prefixed by '[feature]' until you have collected positive feedback about the change. 34 | 35 | #### **Questions about the source code** 36 | 37 | * Open an issue on GitHub prefixed by '[misc]', describe as clear as possible. 38 | 39 | Thanks! 40 | 41 | Winshining 42 | -------------------------------------------------------------------------------- /ngx_rtmp_amf.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | */ 5 | 6 | 7 | #ifndef _NGX_RTMP_AMF_H_INCLUDED_ 8 | #define _NGX_RTMP_AMF_H_INCLUDED_ 9 | 10 | 11 | #include 12 | #include 13 | 14 | 15 | /* basic types */ 16 | #define NGX_RTMP_AMF_NUMBER 0x00 17 | #define NGX_RTMP_AMF_BOOLEAN 0x01 18 | #define NGX_RTMP_AMF_STRING 0x02 19 | #define NGX_RTMP_AMF_OBJECT 0x03 20 | #define NGX_RTMP_AMF_NULL 0x05 21 | #define NGX_RTMP_AMF_ARRAY_NULL 0x06 22 | #define NGX_RTMP_AMF_MIXED_ARRAY 0x08 23 | #define NGX_RTMP_AMF_END 0x09 24 | #define NGX_RTMP_AMF_ARRAY 0x0a 25 | 26 | /* extended types */ 27 | #define NGX_RTMP_AMF_INT8 0x0100 28 | #define NGX_RTMP_AMF_INT16 0x0101 29 | #define NGX_RTMP_AMF_INT32 0x0102 30 | #define NGX_RTMP_AMF_VARIANT_ 0x0103 31 | 32 | /* r/w flags */ 33 | #define NGX_RTMP_AMF_OPTIONAL 0x1000 34 | #define NGX_RTMP_AMF_TYPELESS 0x2000 35 | #define NGX_RTMP_AMF_CONTEXT 0x4000 36 | 37 | #define NGX_RTMP_AMF_VARIANT (NGX_RTMP_AMF_VARIANT_\ 38 | |NGX_RTMP_AMF_TYPELESS) 39 | 40 | 41 | typedef struct { 42 | ngx_int_t type; 43 | ngx_str_t name; 44 | void *data; 45 | size_t len; 46 | } ngx_rtmp_amf_elt_t; 47 | 48 | 49 | typedef ngx_chain_t * (*ngx_rtmp_amf_alloc_pt)(void *arg); 50 | 51 | 52 | typedef struct { 53 | ngx_chain_t *link, *first; 54 | size_t offset; 55 | ngx_rtmp_amf_alloc_pt alloc; 56 | void *arg; 57 | ngx_log_t *log; 58 | } ngx_rtmp_amf_ctx_t; 59 | 60 | 61 | /* reading AMF */ 62 | ngx_int_t ngx_rtmp_amf_read(ngx_rtmp_amf_ctx_t *ctx, 63 | ngx_rtmp_amf_elt_t *elts, size_t nelts); 64 | 65 | /* writing AMF */ 66 | ngx_int_t ngx_rtmp_amf_write(ngx_rtmp_amf_ctx_t *ctx, 67 | ngx_rtmp_amf_elt_t *elts, size_t nelts); 68 | 69 | 70 | #endif /* _NGX_RTMP_AMF_H_INCLUDED_ */ 71 | 72 | -------------------------------------------------------------------------------- /ngx_rtmp_netcall_module.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | */ 5 | 6 | 7 | #ifndef _NGX_RTMP_NETCALL_H_INCLUDED_ 8 | #define _NGX_RTMP_NETCALL_H_INCLUDED_ 9 | 10 | 11 | #include 12 | #include 13 | #include "ngx_rtmp.h" 14 | 15 | 16 | typedef ngx_chain_t * (*ngx_rtmp_netcall_create_pt)(ngx_rtmp_session_t *s, 17 | void *arg, ngx_pool_t *pool); 18 | typedef ngx_int_t (*ngx_rtmp_netcall_filter_pt)(ngx_chain_t *in); 19 | typedef ngx_int_t (*ngx_rtmp_netcall_sink_pt)(ngx_rtmp_session_t *s, 20 | ngx_chain_t *in); 21 | typedef ngx_int_t (*ngx_rtmp_netcall_handle_pt)(ngx_rtmp_session_t *s, 22 | void *arg, ngx_chain_t *in); 23 | 24 | #define NGX_RTMP_NETCALL_HTTP_GET 0 25 | #define NGX_RTMP_NETCALL_HTTP_POST 1 26 | 27 | 28 | /* If handle is NULL then netcall is created detached 29 | * which means it's completely independent of RTMP 30 | * session and its result is never visible to anyone. 31 | * 32 | * WARNING: It's not recommended to create non-detached 33 | * netcalls from disconect handlers. Netcall disconnect 34 | * handler which detaches active netcalls is executed 35 | * BEFORE your handler. It leads to a crash 36 | * after netcall connection is closed */ 37 | typedef struct { 38 | ngx_url_t *url; 39 | ngx_rtmp_netcall_create_pt create; 40 | ngx_rtmp_netcall_filter_pt filter; 41 | ngx_rtmp_netcall_sink_pt sink; 42 | ngx_rtmp_netcall_handle_pt handle; 43 | void *arg; 44 | size_t argsize; 45 | } ngx_rtmp_netcall_init_t; 46 | 47 | 48 | ngx_int_t ngx_rtmp_netcall_create(ngx_rtmp_session_t *s, 49 | ngx_rtmp_netcall_init_t *ci); 50 | 51 | 52 | /* HTTP handling */ 53 | ngx_chain_t * ngx_rtmp_netcall_http_format_session(ngx_rtmp_session_t *s, 54 | ngx_pool_t *pool); 55 | ngx_chain_t * ngx_rtmp_netcall_http_format_request(ngx_int_t method, 56 | ngx_str_t *host, ngx_str_t *uri, ngx_chain_t *args, ngx_chain_t *body, 57 | ngx_pool_t *pool, ngx_str_t *content_type); 58 | ngx_chain_t * ngx_rtmp_netcall_http_skip_header(ngx_chain_t *in); 59 | 60 | 61 | /* Memcache handling */ 62 | ngx_chain_t * ngx_rtmp_netcall_memcache_set(ngx_rtmp_session_t *s, 63 | ngx_pool_t *pool, ngx_str_t *key, ngx_str_t *value, 64 | ngx_uint_t flags, ngx_uint_t sec); 65 | 66 | 67 | #endif /* _NGX_RTMP_NETCALL_H_INCLUDED_ */ 68 | -------------------------------------------------------------------------------- /test/rtmp-publisher/RtmpPlayer.mxml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /ngx_http_flv_live_module.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Winshining 4 | */ 5 | 6 | #ifndef _NGX_HTTP_FLV_LIVE_H_INCLUDED_ 7 | #define _NGX_HTTP_FLV_LIVE_H_INCLUDED_ 8 | 9 | 10 | #include "ngx_rtmp_cmd_module.h" 11 | #include "ngx_rtmp_live_module.h" 12 | #include "ngx_rtmp_codec_module.h" 13 | 14 | 15 | #define NGX_HASH_MAX_SIZE 0x80 16 | #define NGX_HASH_MAX_BUKET_SIZE 0x40 17 | #define NGX_BUFF_MAX_SIZE 0x80 18 | #define NGX_FLV_TAG_HEADER_SIZE 11 19 | 20 | 21 | extern ngx_module_t ngx_rtmp_module; 22 | 23 | 24 | extern ngx_rtmp_play_pt http_flv_live_next_play; 25 | extern ngx_rtmp_close_stream_pt http_flv_live_next_close_stream; 26 | 27 | 28 | #define ngx_rtmp_cycle_get_module_main_conf(cycle, module) \ 29 | (cycle->conf_ctx[ngx_rtmp_module.index] ? \ 30 | ((ngx_rtmp_conf_ctx_t *) cycle->conf_ctx[ngx_rtmp_module.index]) \ 31 | ->main_conf[module.ctx_index]: \ 32 | NULL) 33 | 34 | 35 | typedef struct ngx_http_flv_live_ctx_s { 36 | ngx_rtmp_session_t *s; 37 | ngx_flag_t header_sent; 38 | 39 | ngx_str_t app; 40 | ngx_str_t port; 41 | ngx_str_t stream; 42 | } ngx_http_flv_live_ctx_t; 43 | 44 | 45 | typedef struct ngx_http_flv_live_conf_s { 46 | ngx_flag_t flv_live; 47 | } ngx_http_flv_live_conf_t; 48 | 49 | 50 | typedef struct { 51 | ngx_chain_t *meta; 52 | ngx_chain_t *apkt; 53 | ngx_chain_t *acopkt; 54 | ngx_chain_t *rpkt; 55 | 56 | ngx_int_t (*send_message_pt)(ngx_rtmp_session_t *s, 57 | ngx_chain_t *out, ngx_uint_t priority); 58 | ngx_chain_t *(*meta_message_pt)(ngx_rtmp_session_t *s, 59 | ngx_chain_t *in); 60 | ngx_chain_t *(*append_message_pt)(ngx_rtmp_session_t *s, 61 | ngx_rtmp_header_t *h, ngx_rtmp_header_t *lh, 62 | ngx_chain_t *in); 63 | void (*free_message_pt)(ngx_rtmp_session_t *s, 64 | ngx_chain_t *in); 65 | } ngx_rtmp_live_proc_handler_t; 66 | 67 | 68 | ngx_int_t ngx_http_flv_live_play(ngx_rtmp_session_t *s, 69 | ngx_rtmp_play_t *v); 70 | ngx_int_t ngx_http_flv_live_close_stream(ngx_rtmp_session_t *s, 71 | ngx_rtmp_close_stream_t *v); 72 | 73 | ngx_int_t ngx_http_flv_live_send_header(ngx_rtmp_session_t *s); 74 | void ngx_http_flv_live_set_status(ngx_rtmp_session_t *s, unsigned active); 75 | 76 | 77 | #endif 78 | 79 | -------------------------------------------------------------------------------- /hls/ngx_rtmp_mpegts_crc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file crc.h 3 | * Functions and types for CRC checks. 4 | * 5 | * Generated on Thu May 5 15:32:22 2016, 6 | * by pycrc v0.9, https://pycrc.org 7 | * using the configuration: 8 | * Width = 32 9 | * Poly = 0x04c11db7 10 | * Xor_In = 0xffffffff 11 | * ReflectIn = False 12 | * Xor_Out = 0x00000000 13 | * ReflectOut = False 14 | * Algorithm = table-driven 15 | *****************************************************************************/ 16 | #ifndef _NGX_RTMP_MPEGTS_CRC_H_INCLUDED_ 17 | #define _NGX_RTMP_MPEGTS_CRC_H_INCLUDED_ 18 | 19 | 20 | #include 21 | 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | 28 | /** 29 | * The definition of the used algorithm. 30 | * 31 | * This is not used anywhere in the generated code, but it may be used by the 32 | * application code to call algoritm-specific code, is desired. 33 | *****************************************************************************/ 34 | #define CRC_ALGO_TABLE_DRIVEN 1 35 | 36 | 37 | /** 38 | * The type of the CRC values. 39 | * 40 | * This type must be big enough to contain at least 32 bits. 41 | *****************************************************************************/ 42 | typedef uint_fast32_t ngx_rtmp_mpegts_crc_t; 43 | 44 | 45 | /** 46 | * Calculate the initial crc value. 47 | * 48 | * \return The initial crc value. 49 | *****************************************************************************/ 50 | static ngx_inline ngx_rtmp_mpegts_crc_t ngx_rtmp_mpegts_crc_init(void) 51 | { 52 | return 0xffffffff; 53 | } 54 | 55 | 56 | /** 57 | * Update the crc value with new data. 58 | * 59 | * \param crc The current crc value. 60 | * \param data Pointer to a buffer of \a data_len bytes. 61 | * \param data_len Number of bytes in the \a data buffer. 62 | * \return The updated crc value. 63 | *****************************************************************************/ 64 | ngx_rtmp_mpegts_crc_t ngx_rtmp_mpegts_crc_update(ngx_rtmp_mpegts_crc_t crc, 65 | const void *data, size_t data_len); 66 | 67 | 68 | /** 69 | * Calculate the final crc value. 70 | * 71 | * \param crc The current crc value. 72 | * \return The final crc value. 73 | *****************************************************************************/ 74 | static ngx_inline ngx_rtmp_mpegts_crc_t 75 | ngx_rtmp_mpegts_crc_finalize(ngx_rtmp_mpegts_crc_t crc) 76 | { 77 | return crc ^ 0x00000000; 78 | } 79 | 80 | 81 | #ifdef __cplusplus 82 | } /* closing brace for extern "C" */ 83 | #endif 84 | 85 | #endif /* _NGX_RTMP_MPEGTS_CRC_H_INCLUDED_ */ 86 | -------------------------------------------------------------------------------- /ngx_rtmp_play_module.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | */ 5 | 6 | 7 | #ifndef _NGX_RTMP_PLAY_H_INCLUDED_ 8 | #define _NGX_RTMP_PLAY_H_INCLUDED_ 9 | 10 | 11 | #include 12 | #include 13 | #include "ngx_rtmp.h" 14 | #include "ngx_rtmp_cmd_module.h" 15 | 16 | 17 | typedef ngx_int_t (*ngx_rtmp_play_init_pt) (ngx_rtmp_session_t *s, 18 | ngx_file_t *f, ngx_int_t aindex, ngx_int_t vindex); 19 | typedef ngx_int_t (*ngx_rtmp_play_done_pt) (ngx_rtmp_session_t *s, 20 | ngx_file_t *f); 21 | typedef ngx_int_t (*ngx_rtmp_play_start_pt) (ngx_rtmp_session_t *s, 22 | ngx_file_t *f); 23 | typedef ngx_int_t (*ngx_rtmp_play_seek_pt) (ngx_rtmp_session_t *s, 24 | ngx_file_t *f, ngx_uint_t offs); 25 | typedef ngx_int_t (*ngx_rtmp_play_stop_pt) (ngx_rtmp_session_t *s, 26 | ngx_file_t *f); 27 | typedef ngx_int_t (*ngx_rtmp_play_send_pt) (ngx_rtmp_session_t *s, 28 | ngx_file_t *f, ngx_uint_t *ts); 29 | 30 | 31 | typedef struct { 32 | ngx_str_t name; 33 | ngx_str_t pfx; 34 | ngx_str_t sfx; 35 | 36 | ngx_rtmp_play_init_pt init; 37 | ngx_rtmp_play_done_pt done; 38 | ngx_rtmp_play_start_pt start; 39 | ngx_rtmp_play_seek_pt seek; 40 | ngx_rtmp_play_stop_pt stop; 41 | ngx_rtmp_play_send_pt send; 42 | } ngx_rtmp_play_fmt_t; 43 | 44 | 45 | typedef struct ngx_rtmp_play_ctx_s ngx_rtmp_play_ctx_t; 46 | 47 | 48 | struct ngx_rtmp_play_ctx_s { 49 | ngx_rtmp_session_t *session; 50 | ngx_file_t file; 51 | ngx_rtmp_play_fmt_t *fmt; 52 | ngx_event_t send_evt; 53 | unsigned playing:1; 54 | unsigned opened:1; 55 | unsigned joined:1; 56 | ngx_uint_t ncrs; 57 | ngx_uint_t nheader; 58 | ngx_uint_t nbody; 59 | size_t pfx_size; 60 | ngx_str_t sfx; 61 | ngx_uint_t file_id; 62 | ngx_int_t aindex, vindex; 63 | ngx_uint_t nentry; 64 | ngx_uint_t post_seek; 65 | u_char name[NGX_RTMP_MAX_NAME]; 66 | ngx_rtmp_play_ctx_t *next; 67 | }; 68 | 69 | 70 | typedef struct { 71 | ngx_str_t *root; 72 | ngx_url_t *url; 73 | } ngx_rtmp_play_entry_t; 74 | 75 | 76 | typedef struct { 77 | ngx_str_t temp_path; 78 | ngx_str_t local_path; 79 | ngx_array_t entries; /* ngx_rtmp_play_entry_t * */ 80 | ngx_uint_t nbuckets; 81 | ngx_rtmp_play_ctx_t **ctx; 82 | } ngx_rtmp_play_app_conf_t; 83 | 84 | 85 | typedef struct { 86 | ngx_array_t fmts; /* ngx_rtmp_play_fmt_t * */ 87 | } ngx_rtmp_play_main_conf_t; 88 | 89 | 90 | extern ngx_module_t ngx_rtmp_play_module; 91 | 92 | 93 | #endif /* _NGX_RTMP_PLAY_H_INCLUDED_ */ 94 | -------------------------------------------------------------------------------- /test/rtmp-publisher/RtmpPublisher.mxml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /ngx_rtmp_shared.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | */ 5 | 6 | 7 | #include 8 | #include 9 | #include "ngx_rtmp.h" 10 | 11 | 12 | ngx_chain_t * 13 | ngx_rtmp_alloc_shared_buf(ngx_rtmp_core_srv_conf_t *cscf) 14 | { 15 | u_char *p; 16 | ngx_chain_t *out; 17 | ngx_buf_t *b; 18 | size_t size; 19 | 20 | if (cscf->free) { 21 | out = cscf->free; 22 | cscf->free = out->next; 23 | 24 | } else { 25 | 26 | size = cscf->chunk_size + NGX_RTMP_MAX_CHUNK_HEADER; 27 | 28 | p = ngx_pcalloc(cscf->pool, NGX_RTMP_REFCOUNT_BYTES 29 | + sizeof(ngx_chain_t) 30 | + sizeof(ngx_buf_t) 31 | + size); 32 | if (p == NULL) { 33 | return NULL; 34 | } 35 | 36 | p += NGX_RTMP_REFCOUNT_BYTES; 37 | out = (ngx_chain_t *)p; 38 | 39 | p += sizeof(ngx_chain_t); 40 | out->buf = (ngx_buf_t *)p; 41 | 42 | p += sizeof(ngx_buf_t); 43 | out->buf->start = p; 44 | out->buf->end = p + size; 45 | } 46 | 47 | out->next = NULL; 48 | b = out->buf; 49 | b->pos = b->last = b->start + NGX_RTMP_MAX_CHUNK_HEADER; 50 | b->memory = 1; 51 | 52 | /* buffer has refcount =1 when created! */ 53 | ngx_rtmp_ref_set(out, 1); 54 | 55 | return out; 56 | } 57 | 58 | 59 | void 60 | ngx_rtmp_free_shared_chain(ngx_rtmp_core_srv_conf_t *cscf, ngx_chain_t *in) 61 | { 62 | ngx_chain_t *cl; 63 | 64 | if (ngx_rtmp_ref_put(in)) { 65 | return; 66 | } 67 | 68 | for (cl = in; ; cl = cl->next) { 69 | if (cl->next == NULL) { 70 | cl->next = cscf->free; 71 | cscf->free = in; 72 | return; 73 | } 74 | } 75 | } 76 | 77 | 78 | ngx_chain_t * 79 | ngx_rtmp_append_shared_bufs(ngx_rtmp_core_srv_conf_t *cscf, 80 | ngx_chain_t *head, ngx_chain_t *in) 81 | { 82 | ngx_chain_t *l, **ll; 83 | u_char *p; 84 | size_t size; 85 | 86 | ll = &head; 87 | p = in->buf->pos; 88 | l = head; 89 | 90 | if (l) { 91 | for(; l->next; l = l->next); 92 | ll = &l->next; 93 | } 94 | 95 | for ( ;; ) { 96 | 97 | if (l == NULL || l->buf->last == l->buf->end) { 98 | l = ngx_rtmp_alloc_shared_buf(cscf); 99 | if (l == NULL || l->buf == NULL) { 100 | break; 101 | } 102 | 103 | *ll = l; 104 | ll = &l->next; 105 | } 106 | 107 | while (l->buf->end - l->buf->last >= in->buf->last - p) { 108 | l->buf->last = ngx_cpymem(l->buf->last, p, 109 | in->buf->last - p); 110 | in = in->next; 111 | if (in == NULL) { 112 | goto done; 113 | } 114 | p = in->buf->pos; 115 | } 116 | 117 | size = l->buf->end - l->buf->last; 118 | l->buf->last = ngx_cpymem(l->buf->last, p, size); 119 | p += size; 120 | } 121 | 122 | done: 123 | *ll = NULL; 124 | 125 | return head; 126 | } 127 | -------------------------------------------------------------------------------- /ngx_rtmp_relay_module.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | */ 5 | 6 | 7 | #ifndef _NGX_RTMP_RELAY_H_INCLUDED_ 8 | #define _NGX_RTMP_RELAY_H_INCLUDED_ 9 | 10 | 11 | #include 12 | #include 13 | #include "ngx_rtmp.h" 14 | 15 | 16 | typedef struct { 17 | ngx_url_t url; 18 | ngx_str_t app; 19 | ngx_str_t name; 20 | ngx_str_t tc_url; 21 | ngx_str_t page_url; 22 | ngx_str_t swf_url; 23 | ngx_str_t flash_ver; 24 | ngx_str_t play_path; 25 | ngx_int_t live; 26 | ngx_int_t start; 27 | ngx_int_t stop; 28 | 29 | void *tag; /* usually module reference */ 30 | void *data; /* module-specific data */ 31 | ngx_uint_t counter; /* mutable connection counter */ 32 | } ngx_rtmp_relay_target_t; 33 | 34 | 35 | typedef struct ngx_rtmp_relay_ctx_s ngx_rtmp_relay_ctx_t; 36 | 37 | struct ngx_rtmp_relay_ctx_s { 38 | ngx_str_t server_name; 39 | ngx_str_t name; 40 | ngx_str_t url; 41 | ngx_log_t log; 42 | ngx_rtmp_session_t *session; 43 | ngx_rtmp_relay_ctx_t *publish; 44 | ngx_rtmp_relay_ctx_t *play; 45 | ngx_rtmp_relay_ctx_t *next; 46 | 47 | ngx_str_t app; 48 | ngx_str_t tc_url; 49 | ngx_str_t page_url; 50 | ngx_str_t swf_url; 51 | ngx_str_t flash_ver; 52 | ngx_str_t play_path; 53 | ngx_int_t live; 54 | ngx_int_t start; 55 | ngx_int_t stop; 56 | 57 | ngx_event_t push_evt; 58 | ngx_event_t *static_evt; 59 | void *tag; 60 | void *data; 61 | }; 62 | 63 | 64 | typedef struct { 65 | ngx_array_t pulls; /* ngx_rtmp_relay_target_t * */ 66 | ngx_array_t pushes; /* ngx_rtmp_relay_target_t * */ 67 | ngx_array_t static_pulls; /* ngx_rtmp_relay_target_t * */ 68 | ngx_array_t static_events; /* ngx_event_t * */ 69 | ngx_log_t *log; 70 | ngx_uint_t nbuckets; 71 | ngx_msec_t buflen; 72 | ngx_flag_t session_relay; 73 | ngx_msec_t push_reconnect; 74 | ngx_msec_t pull_reconnect; 75 | ngx_rtmp_relay_ctx_t **ctx; 76 | } ngx_rtmp_relay_app_conf_t; 77 | 78 | 79 | extern ngx_module_t ngx_rtmp_relay_module; 80 | 81 | 82 | ngx_int_t ngx_rtmp_relay_pull(ngx_rtmp_session_t *s, ngx_str_t *name, 83 | ngx_rtmp_relay_target_t *target); 84 | ngx_int_t ngx_rtmp_relay_push(ngx_rtmp_session_t *s, ngx_str_t *name, 85 | ngx_rtmp_relay_target_t *target); 86 | 87 | 88 | #endif /* _NGX_RTMP_RELAY_H_INCLUDED_ */ 89 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at winshining@163.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /ngx_rtmp_live_module.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | * Copyright (C) Winshining 5 | */ 6 | 7 | 8 | #ifndef _NGX_RTMP_LIVE_H_INCLUDED_ 9 | #define _NGX_RTMP_LIVE_H_INCLUDED_ 10 | 11 | 12 | #include 13 | #include 14 | #include "ngx_rtmp.h" 15 | #include "ngx_rtmp_cmd_module.h" 16 | #include "ngx_rtmp_bandwidth.h" 17 | #include "ngx_rtmp_streams.h" 18 | 19 | 20 | typedef struct ngx_rtmp_live_ctx_s ngx_rtmp_live_ctx_t; 21 | typedef struct ngx_rtmp_live_stream_s ngx_rtmp_live_stream_t; 22 | 23 | 24 | typedef struct { 25 | unsigned active:1; 26 | uint32_t timestamp; 27 | uint32_t csid; 28 | uint32_t dropped; 29 | } ngx_rtmp_live_chunk_stream_t; 30 | 31 | 32 | struct ngx_rtmp_live_ctx_s { 33 | ngx_rtmp_session_t *session; 34 | ngx_rtmp_live_stream_t *stream; 35 | ngx_rtmp_live_ctx_t *next; 36 | ngx_uint_t ndropped; 37 | ngx_rtmp_live_chunk_stream_t cs[2]; 38 | ngx_uint_t meta_version; 39 | ngx_event_t idle_evt; 40 | unsigned active:1; 41 | unsigned publishing:1; 42 | unsigned silent:1; 43 | unsigned paused:1; 44 | ngx_uint_t protocol; 45 | }; 46 | 47 | 48 | struct ngx_rtmp_live_stream_s { 49 | u_char name[NGX_RTMP_MAX_NAME]; 50 | ngx_rtmp_live_stream_t *next; 51 | ngx_rtmp_live_ctx_t *ctx; 52 | ngx_rtmp_live_ctx_t *pub_ctx; 53 | ngx_rtmp_bandwidth_t bw_in; 54 | ngx_rtmp_bandwidth_t bw_in_audio; 55 | ngx_rtmp_bandwidth_t bw_in_video; 56 | ngx_rtmp_bandwidth_t bw_in_data; 57 | ngx_rtmp_bandwidth_t bw_out; 58 | ngx_msec_t epoch; 59 | unsigned active:1; 60 | unsigned publishing:1; 61 | }; 62 | 63 | 64 | typedef struct { 65 | ngx_int_t nbuckets; 66 | ngx_rtmp_live_stream_t **streams; 67 | ngx_flag_t live; 68 | ngx_flag_t meta; 69 | ngx_msec_t sync; 70 | ngx_msec_t idle_timeout; 71 | ngx_flag_t atc; 72 | ngx_flag_t interleave; 73 | ngx_flag_t wait_key; 74 | ngx_flag_t wait_video; 75 | ngx_flag_t publish_notify; 76 | ngx_flag_t play_restart; 77 | ngx_flag_t idle_streams; 78 | ngx_msec_t buflen; 79 | ngx_pool_t *pool; 80 | ngx_rtmp_live_stream_t *free_streams; 81 | } ngx_rtmp_live_app_conf_t; 82 | 83 | 84 | extern ngx_module_t ngx_rtmp_live_module; 85 | 86 | 87 | ngx_rtmp_live_stream_t **ngx_rtmp_live_get_stream(ngx_rtmp_session_t *s, 88 | u_char *name, int create); 89 | 90 | 91 | #endif /* _NGX_RTMP_LIVE_H_INCLUDED_ */ 92 | -------------------------------------------------------------------------------- /test/rtmp-publisher/RtmpPlayerLight.mxml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /ngx_rtmp_variables.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Igor Sysoev 4 | * Copyright (C) Nginx, Inc. 5 | * Copyright (C) Winshining 6 | */ 7 | 8 | 9 | #ifndef _NGX_RTMP_VARIABLES_H_INCLUDED_ 10 | #define _NGX_RTMP_VARIABLES_H_INCLUDED_ 11 | 12 | 13 | #include 14 | #include 15 | 16 | 17 | typedef ngx_variable_value_t ngx_rtmp_variable_value_t; 18 | 19 | #define ngx_rtmp_variable(v) { sizeof(v) - 1, 1, 0, 0, 0, (u_char *) v } 20 | 21 | typedef struct ngx_rtmp_variable_s ngx_rtmp_variable_t; 22 | 23 | typedef void (*ngx_rtmp_set_variable_pt) (ngx_rtmp_session_t *s, 24 | ngx_rtmp_variable_value_t *v, uintptr_t data); 25 | typedef ngx_int_t (*ngx_rtmp_get_variable_pt) (ngx_rtmp_session_t *s, 26 | ngx_rtmp_variable_value_t *v, uintptr_t data); 27 | 28 | 29 | #define NGX_RTMP_VAR_CHANGEABLE 1 30 | #define NGX_RTMP_VAR_NOCACHEABLE 2 31 | #define NGX_RTMP_VAR_INDEXED 4 32 | #define NGX_RTMP_VAR_NOHASH 8 33 | #define NGX_RTMP_VAR_WEAK 16 34 | #define NGX_RTMP_VAR_PREFIX 32 35 | 36 | 37 | struct ngx_rtmp_variable_s { 38 | ngx_str_t name; /* must be first to build the hash */ 39 | ngx_rtmp_set_variable_pt set_handler; 40 | ngx_rtmp_get_variable_pt get_handler; 41 | uintptr_t data; 42 | ngx_uint_t flags; 43 | ngx_uint_t index; 44 | }; 45 | 46 | 47 | ngx_rtmp_variable_t *ngx_rtmp_add_variable(ngx_conf_t *cf, ngx_str_t *name, 48 | ngx_uint_t flags); 49 | ngx_int_t ngx_rtmp_get_variable_index(ngx_conf_t *cf, ngx_str_t *name); 50 | ngx_rtmp_variable_value_t *ngx_rtmp_get_indexed_variable(ngx_rtmp_session_t *s, 51 | ngx_uint_t index); 52 | ngx_rtmp_variable_value_t *ngx_rtmp_get_flushed_variable(ngx_rtmp_session_t *s, 53 | ngx_uint_t index); 54 | 55 | ngx_rtmp_variable_value_t *ngx_rtmp_get_variable(ngx_rtmp_session_t *s, 56 | ngx_str_t *name, ngx_uint_t key); 57 | 58 | 59 | #if (NGX_PCRE) 60 | 61 | typedef struct { 62 | ngx_uint_t capture; 63 | ngx_int_t index; 64 | } ngx_rtmp_regex_variable_t; 65 | 66 | 67 | typedef struct { 68 | ngx_regex_t *regex; 69 | ngx_uint_t ncaptures; 70 | ngx_rtmp_regex_variable_t *variables; 71 | ngx_uint_t nvariables; 72 | ngx_str_t name; 73 | } ngx_rtmp_regex_t; 74 | 75 | 76 | typedef struct { 77 | ngx_rtmp_regex_t *regex; 78 | void *value; 79 | } ngx_rtmp_map_regex_t; 80 | 81 | 82 | ngx_rtmp_regex_t *ngx_rtmp_regex_compile(ngx_conf_t *cf, 83 | ngx_regex_compile_t *rc); 84 | ngx_int_t ngx_rtmp_regex_exec(ngx_rtmp_session_t *s, ngx_rtmp_regex_t *re, 85 | ngx_str_t *str); 86 | 87 | #endif 88 | 89 | 90 | typedef struct { 91 | ngx_hash_combined_t hash; 92 | #if (NGX_PCRE) 93 | ngx_rtmp_map_regex_t *regex; 94 | ngx_uint_t nregex; 95 | #endif 96 | } ngx_rtmp_map_t; 97 | 98 | 99 | void *ngx_rtmp_map_find(ngx_rtmp_session_t *s, ngx_rtmp_map_t *map, 100 | ngx_str_t *match); 101 | 102 | 103 | ngx_int_t ngx_rtmp_variables_add_core_vars(ngx_conf_t *cf); 104 | ngx_int_t ngx_rtmp_variables_init_vars(ngx_conf_t *cf); 105 | 106 | 107 | extern ngx_rtmp_variable_value_t ngx_rtmp_variable_null_value; 108 | extern ngx_rtmp_variable_value_t ngx_rtmp_variable_true_value; 109 | 110 | 111 | #endif /* _NGX_RTMP_VARIABLES_H_INCLUDED_ */ 112 | -------------------------------------------------------------------------------- /ngx_rtmp_record_module.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | * Copyright (C) Winshining 5 | */ 6 | 7 | 8 | #ifndef _NGX_RTMP_RECORD_H_INCLUDED_ 9 | #define _NGX_RTMP_RECORD_H_INCLUDED_ 10 | 11 | 12 | #include 13 | #include 14 | #include "ngx_rtmp.h" 15 | 16 | 17 | #define NGX_RTMP_RECORD_OFF 0x01 18 | #define NGX_RTMP_RECORD_AUDIO 0x02 19 | #define NGX_RTMP_RECORD_VIDEO 0x04 20 | #define NGX_RTMP_RECORD_KEYFRAMES 0x08 21 | #define NGX_RTMP_RECORD_MANUAL 0x10 22 | 23 | 24 | typedef struct { 25 | ngx_str_t id; 26 | ngx_uint_t flags; 27 | ngx_str_t path; 28 | size_t max_size; 29 | size_t max_frames; 30 | ngx_msec_t interval; 31 | ngx_str_t suffix; 32 | ngx_flag_t unique; 33 | ngx_flag_t append; 34 | ngx_flag_t lock_file; 35 | ngx_flag_t notify; 36 | ngx_url_t *url; 37 | 38 | void **rec_conf; 39 | ngx_array_t rec; /* ngx_rtmp_record_app_conf_t * */ 40 | } ngx_rtmp_record_app_conf_t; 41 | 42 | 43 | typedef struct { 44 | ngx_rtmp_record_app_conf_t *conf; 45 | ngx_file_t file; 46 | ngx_uint_t nframes; 47 | uint32_t epoch, time_shift; 48 | ngx_time_t last; 49 | time_t timestamp; 50 | unsigned failed:1; 51 | unsigned initialized:1; 52 | unsigned aac_header_sent:1; 53 | unsigned avc_header_sent:1; 54 | unsigned video_key_sent:1; 55 | unsigned audio:1; 56 | unsigned video:1; 57 | } ngx_rtmp_record_rec_ctx_t; 58 | 59 | 60 | typedef struct { 61 | ngx_array_t rec; /* ngx_rtmp_record_rec_ctx_t */ 62 | u_char name[NGX_RTMP_MAX_NAME]; 63 | u_char args[NGX_RTMP_MAX_ARGS]; 64 | } ngx_rtmp_record_ctx_t; 65 | 66 | 67 | ngx_uint_t ngx_rtmp_record_find(ngx_rtmp_record_app_conf_t *racf, 68 | ngx_str_t *id); 69 | 70 | 71 | /* Manual recording control, 72 | * 'n' is record node index in config array. 73 | * Note: these functions allocate path in static buffer */ 74 | 75 | ngx_int_t ngx_rtmp_record_open(ngx_rtmp_session_t *s, ngx_uint_t n, 76 | ngx_str_t *path); 77 | ngx_int_t ngx_rtmp_record_close(ngx_rtmp_session_t *s, ngx_uint_t n, 78 | ngx_str_t *path); 79 | 80 | void ngx_rtmp_record_get_path(ngx_rtmp_session_t *s, 81 | ngx_rtmp_record_rec_ctx_t *rctx, ngx_str_t *path); 82 | 83 | 84 | typedef struct { 85 | ngx_str_t recorder; 86 | ngx_str_t path; 87 | } ngx_rtmp_record_done_t; 88 | 89 | 90 | typedef ngx_int_t (*ngx_rtmp_record_done_pt)(ngx_rtmp_session_t *s, 91 | ngx_rtmp_record_done_t *v); 92 | 93 | 94 | extern ngx_rtmp_record_done_pt ngx_rtmp_record_done; 95 | 96 | 97 | extern ngx_module_t ngx_rtmp_record_module; 98 | 99 | 100 | #endif /* _NGX_RTMP_RECORD_H_INCLUDED_ */ 101 | -------------------------------------------------------------------------------- /ngx_rtmp_codec_module.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | * Copyright (C) Winshining 5 | */ 6 | 7 | 8 | #ifndef _NGX_RTMP_CODEC_H_INCLUDED_ 9 | #define _NGX_RTMP_CODEC_H_INCLUDED_ 10 | 11 | 12 | #include 13 | #include 14 | #include "ngx_rtmp.h" 15 | 16 | 17 | /* AVC NAL unit types */ 18 | enum { 19 | NGX_RTMP_NALU_SLICE = 1, 20 | NGX_RTMP_NALU_DPA = 2, 21 | NGX_RTMP_NALU_DPB = 3, 22 | NGX_RTMP_NALU_DPC = 4, 23 | NGX_RTMP_NALU_IDR = 5, 24 | NGX_RTMP_NALU_SEI = 6, 25 | NGX_RTMP_NALU_SPS = 7, 26 | NGX_RTMP_NALU_PPS = 8, 27 | NGX_RTMP_NALU_AUD = 9, 28 | NGX_RTMP_NALU_EOSEQ = 10, 29 | NGX_RTMP_NALU_EOSTREAM = 11, 30 | NGX_RTMP_NALU_FILL = 12, 31 | NGX_RTMP_NALU_SPS_EXT = 13, 32 | NGX_RTMP_NALU_AUXILIARY_SLICE = 19 33 | }; 34 | 35 | 36 | /* AVC frame types */ 37 | enum { 38 | NGX_RTMP_FRAME_IDR = 1, 39 | NGX_RTMP_FRAME_INTER = 2, 40 | NGX_RTMP_FRAME_DISPOSABLE = 3, 41 | NGX_RTMP_FRAME_GENERATED = 4, 42 | NGX_RTMP_FRAME_VIDEOINFOCMD = 5 43 | }; 44 | 45 | 46 | /* Audio codecs */ 47 | enum { 48 | /* Uncompressed codec id is actually 0, 49 | * but we use another value for consistency */ 50 | NGX_RTMP_AUDIO_UNCOMPRESSED = 16, 51 | NGX_RTMP_AUDIO_ADPCM = 1, 52 | NGX_RTMP_AUDIO_MP3 = 2, 53 | NGX_RTMP_AUDIO_LINEAR_LE = 3, 54 | NGX_RTMP_AUDIO_NELLY16 = 4, 55 | NGX_RTMP_AUDIO_NELLY8 = 5, 56 | NGX_RTMP_AUDIO_NELLY = 6, 57 | NGX_RTMP_AUDIO_G711A = 7, 58 | NGX_RTMP_AUDIO_G711U = 8, 59 | NGX_RTMP_AUDIO_AAC = 10, 60 | NGX_RTMP_AUDIO_SPEEX = 11, 61 | NGX_RTMP_AUDIO_MP3_8 = 14, 62 | NGX_RTMP_AUDIO_DEVSPEC = 15 63 | }; 64 | 65 | 66 | /* Video codecs */ 67 | enum { 68 | NGX_RTMP_VIDEO_JPEG = 1, 69 | NGX_RTMP_VIDEO_SORENSON_H263 = 2, 70 | NGX_RTMP_VIDEO_SCREEN = 3, 71 | NGX_RTMP_VIDEO_ON2_VP6 = 4, 72 | NGX_RTMP_VIDEO_ON2_VP6_ALPHA = 5, 73 | NGX_RTMP_VIDEO_SCREEN2 = 6, 74 | NGX_RTMP_VIDEO_H264 = 7 75 | }; 76 | 77 | 78 | u_char * ngx_rtmp_get_audio_codec_name(ngx_uint_t id); 79 | u_char * ngx_rtmp_get_video_codec_name(ngx_uint_t id); 80 | 81 | 82 | #define NGX_RTMP_SPS_MAX_LENGTH 256 83 | 84 | typedef struct { 85 | ngx_uint_t width; 86 | ngx_uint_t height; 87 | double duration; 88 | double frame_rate; 89 | double video_data_rate; 90 | ngx_uint_t video_codec_id; 91 | double audio_data_rate; 92 | ngx_uint_t audio_codec_id; 93 | ngx_uint_t aac_profile; 94 | ngx_uint_t aac_chan_conf; 95 | ngx_uint_t aac_sbr; 96 | ngx_uint_t aac_ps; 97 | ngx_uint_t avc_profile; 98 | ngx_uint_t avc_compat; 99 | ngx_uint_t avc_level; 100 | ngx_uint_t avc_nal_bytes; 101 | ngx_uint_t avc_ref_frames; 102 | ngx_uint_t sample_rate; /* 5512, 11025, 22050, 44100 */ 103 | ngx_uint_t sample_size; /* 1=8bit, 2=16bit */ 104 | ngx_uint_t audio_channels; /* 1, 2 */ 105 | u_char profile[32]; 106 | u_char level[32]; 107 | 108 | ngx_chain_t *avc_header; 109 | ngx_chain_t *aac_header; 110 | 111 | ngx_chain_t *meta; 112 | ngx_uint_t meta_version; 113 | } ngx_rtmp_codec_ctx_t; 114 | 115 | 116 | extern ngx_module_t ngx_rtmp_codec_module; 117 | 118 | 119 | #endif /* _NGX_RTMP_LIVE_H_INCLUDED_ */ 120 | -------------------------------------------------------------------------------- /ngx_rtmp_proxy_protocol.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | */ 5 | 6 | 7 | #include 8 | #include 9 | #include 10 | #include "ngx_rtmp_proxy_protocol.h" 11 | 12 | 13 | static void ngx_rtmp_proxy_protocol_recv(ngx_event_t *rev); 14 | 15 | 16 | void 17 | ngx_rtmp_proxy_protocol(ngx_rtmp_session_t *s) 18 | { 19 | ngx_event_t *rev; 20 | ngx_connection_t *c; 21 | 22 | c = s->connection; 23 | rev = c->read; 24 | rev->handler = ngx_rtmp_proxy_protocol_recv; 25 | 26 | ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, 27 | "proxy_protocol: start"); 28 | 29 | if (rev->ready) { 30 | /* the deferred accept(), rtsig, aio, iocp */ 31 | 32 | if (ngx_use_accept_mutex) { 33 | ngx_post_event(rev, &ngx_posted_events); 34 | return; 35 | } 36 | 37 | rev->handler(rev); 38 | return; 39 | } 40 | 41 | ngx_add_timer(rev, s->timeout); 42 | 43 | if (ngx_handle_read_event(rev, 0) != NGX_OK) { 44 | ngx_rtmp_finalize_session(s); 45 | return; 46 | } 47 | } 48 | 49 | 50 | static void 51 | ngx_rtmp_proxy_protocol_recv(ngx_event_t *rev) 52 | { 53 | u_char buf[107], *p, *pp, *text; 54 | size_t len; 55 | ssize_t n; 56 | ngx_err_t err; 57 | ngx_int_t i; 58 | ngx_addr_t addr; 59 | ngx_connection_t *c; 60 | ngx_rtmp_session_t *s; 61 | 62 | c = rev->data; 63 | s = c->data; 64 | 65 | if (c->destroyed) { 66 | return; 67 | } 68 | 69 | if (rev->timedout) { 70 | ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, 71 | "proxy_protocol: recv: client timed out"); 72 | c->timedout = 1; 73 | ngx_rtmp_finalize_session(s); 74 | return; 75 | } 76 | 77 | if (rev->timer_set) { 78 | ngx_del_timer(rev); 79 | } 80 | 81 | n = recv(c->fd, (char *) buf, sizeof(buf), MSG_PEEK); 82 | 83 | err = ngx_socket_errno; 84 | 85 | ngx_log_debug1(NGX_LOG_DEBUG_RTMP, c->log, 0, "recv(): %d", n); 86 | 87 | if (n == -1) { 88 | 89 | if (err == NGX_EAGAIN) { 90 | ngx_add_timer(rev, s->timeout); 91 | 92 | if (ngx_handle_read_event(c->read, 0) != NGX_OK) { 93 | ngx_rtmp_finalize_session(s); 94 | } 95 | 96 | return; 97 | } 98 | 99 | ngx_rtmp_finalize_session(s); 100 | 101 | return; 102 | } 103 | 104 | p = buf; 105 | 106 | if (n <= 8 && ngx_strncmp(p, "PROXY ", 6) != 0) { 107 | goto bad_header; 108 | } 109 | 110 | n -= 6; 111 | p += 6; 112 | 113 | ngx_memzero(&addr, sizeof(ngx_addr_t)); 114 | 115 | if (n >= 7 && ngx_strncmp(p, "UNKNOWN", 7) == 0) { 116 | n -= 7; 117 | p += 7; 118 | goto skip; 119 | } 120 | 121 | if (n < 5 || ngx_strncmp(p, "TCP", 3) != 0 122 | || (p[3] != '4' && p[3] != '6') || p[4] != ' ') 123 | { 124 | goto bad_header; 125 | } 126 | 127 | n -= 5; 128 | p += 5; 129 | 130 | pp = ngx_strlchr(p, p + n, ' '); 131 | 132 | if (pp == NULL) { 133 | goto bad_header; 134 | } 135 | 136 | if (ngx_parse_addr(s->connection->pool, &addr, p, pp - p) != NGX_OK) { 137 | goto bad_header; 138 | } 139 | 140 | n -= pp - p; 141 | p = pp; 142 | 143 | skip: 144 | 145 | for (i = 0; i + 1 < n; i++) { 146 | if (p[i] == CR && p[i + 1] == LF) { 147 | break; 148 | } 149 | } 150 | 151 | if (i + 1 >= n) { 152 | goto bad_header; 153 | } 154 | 155 | n = p - buf + i + 2; 156 | 157 | if (c->recv(c, buf, n) != n) { 158 | goto failed; 159 | } 160 | 161 | if (addr.socklen) { 162 | text = ngx_palloc(s->connection->pool, NGX_SOCKADDR_STRLEN); 163 | 164 | if (text == NULL) { 165 | goto failed; 166 | } 167 | 168 | len = ngx_sock_ntop(addr.sockaddr, 169 | #if (nginx_version >= 1005003) 170 | addr.socklen, 171 | #endif 172 | text, NGX_SOCKADDR_STRLEN, 0); 173 | if (len == 0) { 174 | goto failed; 175 | } 176 | 177 | c->sockaddr = addr.sockaddr; 178 | c->socklen = addr.socklen; 179 | c->addr_text.data = text; 180 | c->addr_text.len = len; 181 | 182 | ngx_log_debug1(NGX_LOG_DEBUG_RTMP, c->log, 0, 183 | "proxy_protocol: remote_addr:'%V'", &c->addr_text); 184 | } 185 | 186 | ngx_rtmp_handshake(s); 187 | 188 | return; 189 | 190 | bad_header: 191 | 192 | ngx_log_error(NGX_LOG_INFO, c->log, 0, "proxy_protocol: bad header"); 193 | 194 | failed: 195 | 196 | ngx_rtmp_finalize_session(s); 197 | } 198 | -------------------------------------------------------------------------------- /hls/ngx_rtmp_mpegts_crc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * \file crc.c 3 | * Functions and types for CRC checks. 4 | * 5 | * Generated on Thu May 5 15:32:31 2016, 6 | * by pycrc v0.9, https://pycrc.org 7 | * using the configuration: 8 | * Width = 32 9 | * Poly = 0x04c11db7 10 | * Xor_In = 0xffffffff 11 | * ReflectIn = False 12 | * Xor_Out = 0x00000000 13 | * ReflectOut = False 14 | * Algorithm = table-driven 15 | *****************************************************************************/ 16 | #include 17 | #include "ngx_rtmp_mpegts_crc.h" /* include the header file generated with pycrc */ 18 | 19 | 20 | /** 21 | * Static table used for the table_driven implementation. 22 | *****************************************************************************/ 23 | static const ngx_rtmp_mpegts_crc_t ngx_rtmp_mpegts_crc_table[256] = { 24 | 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 25 | 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 26 | 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, 27 | 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, 28 | 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 29 | 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, 30 | 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, 31 | 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 32 | 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, 33 | 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 34 | 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 35 | 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 36 | 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, 37 | 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 38 | 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 39 | 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, 40 | 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 41 | 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, 42 | 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, 43 | 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 44 | 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, 45 | 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, 46 | 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 47 | 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, 48 | 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 49 | 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 50 | 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 51 | 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 52 | 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 53 | 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 54 | 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, 55 | 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 56 | }; 57 | 58 | 59 | /** 60 | * Update the crc value with new data. 61 | * 62 | * \param crc The current crc value. 63 | * \param data Pointer to a buffer of \a data_len bytes. 64 | * \param data_len Number of bytes in the \a data buffer. 65 | * \return The updated crc value. 66 | *****************************************************************************/ 67 | ngx_rtmp_mpegts_crc_t 68 | ngx_rtmp_mpegts_crc_update(ngx_rtmp_mpegts_crc_t crc, const void *data, size_t data_len) 69 | { 70 | uint32_t tbl_idx; 71 | const u_char *d = (const unsigned char *) data; 72 | 73 | while (data_len--) { 74 | tbl_idx = ((crc >> 24) ^ *d) & 0xff; 75 | crc = (ngx_rtmp_mpegts_crc_table[tbl_idx] ^ (crc << 8)) & 0xffffffff; 76 | 77 | d++; 78 | } 79 | 80 | return crc & 0xffffffff; 81 | } 82 | -------------------------------------------------------------------------------- /ngx_rtmp_cmd_module.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | */ 5 | 6 | 7 | #ifndef _NGX_RTMP_CMD_H_INCLUDED_ 8 | #define _NGX_RTMP_CMD_H_INCLUDED_ 9 | 10 | 11 | #include 12 | #include 13 | #include 14 | #include "ngx_rtmp.h" 15 | 16 | 17 | #define NGX_RTMP_MAX_NAME 256 18 | #define NGX_RTMP_MAX_URL 256 19 | #define NGX_RTMP_MAX_ARGS NGX_RTMP_MAX_NAME 20 | 21 | 22 | /* Basic RTMP call support */ 23 | 24 | typedef struct { 25 | double trans; 26 | u_char app[NGX_RTMP_MAX_NAME]; 27 | u_char args[NGX_RTMP_MAX_ARGS]; 28 | u_char flashver[64]; 29 | u_char swf_url[NGX_RTMP_MAX_URL]; 30 | u_char tc_url[NGX_RTMP_MAX_URL]; 31 | double acodecs; 32 | double vcodecs; 33 | u_char page_url[NGX_RTMP_MAX_URL]; 34 | u_char server_name[NGX_RTMP_MAX_URL]; 35 | double object_encoding; 36 | } ngx_rtmp_connect_t; 37 | 38 | 39 | typedef struct { 40 | double trans; 41 | double stream; 42 | } ngx_rtmp_create_stream_t; 43 | 44 | 45 | typedef struct { 46 | double stream; 47 | } ngx_rtmp_delete_stream_t; 48 | 49 | 50 | typedef struct { 51 | double stream; 52 | } ngx_rtmp_close_stream_t; 53 | 54 | 55 | typedef struct { 56 | u_char name[NGX_RTMP_MAX_NAME]; 57 | u_char args[NGX_RTMP_MAX_ARGS]; 58 | u_char type[16]; 59 | int silent; 60 | } ngx_rtmp_publish_t; 61 | 62 | 63 | typedef struct { 64 | u_char name[NGX_RTMP_MAX_NAME]; 65 | u_char args[NGX_RTMP_MAX_ARGS]; 66 | double start; 67 | double duration; 68 | int reset; 69 | int silent; 70 | } ngx_rtmp_play_t; 71 | 72 | 73 | typedef struct { 74 | double offset; 75 | } ngx_rtmp_seek_t; 76 | 77 | 78 | typedef struct { 79 | uint8_t pause; 80 | double position; 81 | } ngx_rtmp_pause_t; 82 | 83 | 84 | typedef struct { 85 | uint32_t msid; 86 | } ngx_rtmp_msid_t; 87 | 88 | 89 | typedef ngx_rtmp_msid_t ngx_rtmp_stream_begin_t; 90 | typedef ngx_rtmp_msid_t ngx_rtmp_stream_eof_t; 91 | typedef ngx_rtmp_msid_t ngx_rtmp_stream_dry_t; 92 | typedef ngx_rtmp_msid_t ngx_rtmp_recorded_t; 93 | 94 | 95 | typedef struct { 96 | uint32_t msid; 97 | uint32_t buflen; 98 | } ngx_rtmp_set_buflen_t; 99 | 100 | 101 | void ngx_rtmp_cmd_fill_args(u_char name[NGX_RTMP_MAX_NAME], 102 | u_char args[NGX_RTMP_MAX_ARGS]); 103 | 104 | 105 | typedef ngx_int_t (*ngx_rtmp_connect_pt)(ngx_rtmp_session_t *s, 106 | ngx_rtmp_connect_t *v); 107 | typedef ngx_int_t (*ngx_rtmp_disconnect_pt)(ngx_rtmp_session_t *s); 108 | typedef ngx_int_t (*ngx_rtmp_create_stream_pt)(ngx_rtmp_session_t *s, 109 | ngx_rtmp_create_stream_t *v); 110 | typedef ngx_int_t (*ngx_rtmp_close_stream_pt)(ngx_rtmp_session_t *s, 111 | ngx_rtmp_close_stream_t *v); 112 | typedef ngx_int_t (*ngx_rtmp_delete_stream_pt)(ngx_rtmp_session_t *s, 113 | ngx_rtmp_delete_stream_t *v); 114 | typedef ngx_int_t (*ngx_rtmp_publish_pt)(ngx_rtmp_session_t *s, 115 | ngx_rtmp_publish_t *v); 116 | typedef ngx_int_t (*ngx_rtmp_play_pt)(ngx_rtmp_session_t *s, 117 | ngx_rtmp_play_t *v); 118 | typedef ngx_int_t (*ngx_rtmp_seek_pt)(ngx_rtmp_session_t *s, 119 | ngx_rtmp_seek_t *v); 120 | typedef ngx_int_t (*ngx_rtmp_pause_pt)(ngx_rtmp_session_t *s, 121 | ngx_rtmp_pause_t *v); 122 | 123 | typedef ngx_int_t (*ngx_rtmp_stream_begin_pt)(ngx_rtmp_session_t *s, 124 | ngx_rtmp_stream_begin_t *v); 125 | typedef ngx_int_t (*ngx_rtmp_stream_eof_pt)(ngx_rtmp_session_t *s, 126 | ngx_rtmp_stream_eof_t *v); 127 | typedef ngx_int_t (*ngx_rtmp_stream_dry_pt)(ngx_rtmp_session_t *s, 128 | ngx_rtmp_stream_dry_t *v); 129 | typedef ngx_int_t (*ngx_rtmp_recorded_pt)(ngx_rtmp_session_t *s, 130 | ngx_rtmp_recorded_t *v); 131 | typedef ngx_int_t (*ngx_rtmp_set_buflen_pt)(ngx_rtmp_session_t *s, 132 | ngx_rtmp_set_buflen_t *v); 133 | 134 | 135 | extern ngx_rtmp_connect_pt ngx_rtmp_connect; 136 | extern ngx_rtmp_disconnect_pt ngx_rtmp_disconnect; 137 | extern ngx_rtmp_create_stream_pt ngx_rtmp_create_stream; 138 | extern ngx_rtmp_close_stream_pt ngx_rtmp_close_stream; 139 | extern ngx_rtmp_delete_stream_pt ngx_rtmp_delete_stream; 140 | extern ngx_rtmp_publish_pt ngx_rtmp_publish; 141 | extern ngx_rtmp_play_pt ngx_rtmp_play; 142 | extern ngx_rtmp_seek_pt ngx_rtmp_seek; 143 | extern ngx_rtmp_pause_pt ngx_rtmp_pause; 144 | 145 | extern ngx_rtmp_stream_begin_pt ngx_rtmp_stream_begin; 146 | extern ngx_rtmp_stream_eof_pt ngx_rtmp_stream_eof; 147 | extern ngx_rtmp_stream_dry_pt ngx_rtmp_stream_dry; 148 | extern ngx_rtmp_set_buflen_pt ngx_rtmp_set_buflen; 149 | extern ngx_rtmp_recorded_pt ngx_rtmp_recorded; 150 | 151 | 152 | #endif /*_NGX_RTMP_CMD_H_INCLUDED_ */ 153 | -------------------------------------------------------------------------------- /ngx_rtmp_limit_module.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | */ 5 | 6 | 7 | #include 8 | #include 9 | #include "ngx_rtmp.h" 10 | 11 | 12 | typedef struct { 13 | ngx_int_t max_conn; 14 | ngx_shm_zone_t *shm_zone; 15 | } ngx_rtmp_limit_main_conf_t; 16 | 17 | 18 | static ngx_str_t shm_name = ngx_string("rtmp_limit"); 19 | 20 | 21 | static ngx_int_t ngx_rtmp_limit_postconfiguration(ngx_conf_t *cf); 22 | static void *ngx_rtmp_limit_create_main_conf(ngx_conf_t *cf); 23 | 24 | 25 | static ngx_command_t ngx_rtmp_limit_commands[] = { 26 | 27 | { ngx_string("max_connections"), 28 | NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, 29 | ngx_conf_set_num_slot, 30 | NGX_RTMP_MAIN_CONF_OFFSET, 31 | offsetof(ngx_rtmp_limit_main_conf_t, max_conn), 32 | NULL }, 33 | 34 | ngx_null_command 35 | }; 36 | 37 | 38 | static ngx_rtmp_module_t ngx_rtmp_limit_module_ctx = { 39 | NULL, /* preconfiguration */ 40 | ngx_rtmp_limit_postconfiguration, /* postconfiguration */ 41 | ngx_rtmp_limit_create_main_conf, /* create main configuration */ 42 | NULL, /* init main configuration */ 43 | NULL, /* create server configuration */ 44 | NULL, /* merge server configuration */ 45 | NULL, /* create app configuration */ 46 | NULL /* merge app configuration */ 47 | }; 48 | 49 | 50 | ngx_module_t ngx_rtmp_limit_module = { 51 | NGX_MODULE_V1, 52 | &ngx_rtmp_limit_module_ctx, /* module context */ 53 | ngx_rtmp_limit_commands, /* module directives */ 54 | NGX_RTMP_MODULE, /* module type */ 55 | NULL, /* init master */ 56 | NULL, /* init module */ 57 | NULL, /* init process */ 58 | NULL, /* init thread */ 59 | NULL, /* exit thread */ 60 | NULL, /* exit process */ 61 | NULL, /* exit master */ 62 | NGX_MODULE_V1_PADDING 63 | }; 64 | 65 | 66 | static void * 67 | ngx_rtmp_limit_create_main_conf(ngx_conf_t *cf) 68 | { 69 | ngx_rtmp_limit_main_conf_t *lmcf; 70 | 71 | lmcf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_limit_main_conf_t)); 72 | if (lmcf == NULL) { 73 | return NULL; 74 | } 75 | 76 | lmcf->max_conn = NGX_CONF_UNSET; 77 | 78 | return lmcf; 79 | } 80 | 81 | 82 | static ngx_int_t 83 | ngx_rtmp_limit_connect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, 84 | ngx_chain_t *in) 85 | { 86 | ngx_rtmp_limit_main_conf_t *lmcf; 87 | ngx_slab_pool_t *shpool; 88 | ngx_shm_zone_t *shm_zone; 89 | uint32_t *nconn, n; 90 | ngx_int_t rc; 91 | 92 | lmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_limit_module); 93 | if (lmcf->max_conn == NGX_CONF_UNSET) { 94 | return NGX_OK; 95 | } 96 | 97 | shm_zone = lmcf->shm_zone; 98 | shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; 99 | nconn = shm_zone->data; 100 | 101 | ngx_shmtx_lock(&shpool->mutex); 102 | n = ++*nconn; 103 | ngx_shmtx_unlock(&shpool->mutex); 104 | 105 | rc = n > (ngx_uint_t) lmcf->max_conn ? NGX_ERROR : NGX_OK; 106 | 107 | ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, 108 | "limit: inc connection counter: %uD", n); 109 | 110 | if (rc != NGX_OK) { 111 | ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, 112 | "limit: too many connections: %uD > %i", 113 | n, lmcf->max_conn); 114 | } 115 | 116 | return rc; 117 | } 118 | 119 | 120 | static ngx_int_t 121 | ngx_rtmp_limit_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, 122 | ngx_chain_t *in) 123 | { 124 | ngx_rtmp_limit_main_conf_t *lmcf; 125 | ngx_slab_pool_t *shpool; 126 | ngx_shm_zone_t *shm_zone; 127 | uint32_t *nconn, n; 128 | 129 | lmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_limit_module); 130 | if (lmcf->max_conn == NGX_CONF_UNSET) { 131 | return NGX_OK; 132 | } 133 | 134 | shm_zone = lmcf->shm_zone; 135 | shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; 136 | nconn = shm_zone->data; 137 | 138 | ngx_shmtx_lock(&shpool->mutex); 139 | n = --*nconn; 140 | ngx_shmtx_unlock(&shpool->mutex); 141 | 142 | (void) n; 143 | ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, 144 | "limit: dec connection counter: %uD", n); 145 | 146 | return NGX_OK; 147 | } 148 | 149 | 150 | static ngx_int_t 151 | ngx_rtmp_limit_shm_init(ngx_shm_zone_t *shm_zone, void *data) 152 | { 153 | ngx_slab_pool_t *shpool; 154 | uint32_t *nconn; 155 | 156 | if (data) { 157 | shm_zone->data = data; 158 | return NGX_OK; 159 | } 160 | 161 | shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; 162 | 163 | nconn = ngx_slab_alloc(shpool, 4); 164 | if (nconn == NULL) { 165 | return NGX_ERROR; 166 | } 167 | 168 | *nconn = 0; 169 | 170 | shm_zone->data = nconn; 171 | 172 | return NGX_OK; 173 | } 174 | 175 | 176 | static ngx_int_t 177 | ngx_rtmp_limit_postconfiguration(ngx_conf_t *cf) 178 | { 179 | ngx_rtmp_core_main_conf_t *cmcf; 180 | ngx_rtmp_limit_main_conf_t *lmcf; 181 | ngx_rtmp_handler_pt *h; 182 | 183 | cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); 184 | 185 | h = ngx_array_push(&cmcf->events[NGX_RTMP_CONNECT]); 186 | *h = ngx_rtmp_limit_connect; 187 | 188 | h = ngx_array_push(&cmcf->events[NGX_RTMP_DISCONNECT]); 189 | *h = ngx_rtmp_limit_disconnect; 190 | 191 | lmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_limit_module); 192 | if (lmcf->max_conn == NGX_CONF_UNSET) { 193 | return NGX_OK; 194 | } 195 | 196 | lmcf->shm_zone = ngx_shared_memory_add(cf, &shm_name, ngx_pagesize * 2, 197 | &ngx_rtmp_limit_module); 198 | if (lmcf->shm_zone == NULL) { 199 | return NGX_ERROR; 200 | } 201 | 202 | lmcf->shm_zone->init = ngx_rtmp_limit_shm_init; 203 | 204 | return NGX_OK; 205 | } 206 | -------------------------------------------------------------------------------- /ngx_rtmp_eval.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Roman Arutyunyan 4 | */ 5 | 6 | 7 | #include 8 | #include 9 | #include "ngx_rtmp_eval.h" 10 | 11 | 12 | #define NGX_RTMP_EVAL_BUFLEN 16 13 | 14 | 15 | static void 16 | ngx_rtmp_eval_session_str(void *ctx, ngx_rtmp_eval_t *e, ngx_str_t *ret) 17 | { 18 | *ret = *(ngx_str_t *) ((u_char *) ctx + e->offset); 19 | } 20 | 21 | 22 | static void 23 | ngx_rtmp_eval_connection_str(void *ctx, ngx_rtmp_eval_t *e, ngx_str_t *ret) 24 | { 25 | ngx_rtmp_session_t *s = ctx; 26 | 27 | *ret = *(ngx_str_t *) ((u_char *) s->connection + e->offset); 28 | } 29 | 30 | 31 | ngx_rtmp_eval_t ngx_rtmp_eval_session[] = { 32 | 33 | { ngx_string("app"), 34 | ngx_rtmp_eval_session_str, 35 | offsetof(ngx_rtmp_session_t, app) }, 36 | 37 | { ngx_string("flashver"), 38 | ngx_rtmp_eval_session_str, 39 | offsetof(ngx_rtmp_session_t, flashver) }, 40 | 41 | { ngx_string("swfurl"), 42 | ngx_rtmp_eval_session_str, 43 | offsetof(ngx_rtmp_session_t, swf_url) }, 44 | 45 | { ngx_string("tcurl"), 46 | ngx_rtmp_eval_session_str, 47 | offsetof(ngx_rtmp_session_t, tc_url) }, 48 | 49 | { ngx_string("pageurl"), 50 | ngx_rtmp_eval_session_str, 51 | offsetof(ngx_rtmp_session_t, page_url) }, 52 | 53 | { ngx_string("addr"), 54 | ngx_rtmp_eval_connection_str, 55 | offsetof(ngx_connection_t, addr_text) }, 56 | 57 | ngx_rtmp_null_eval 58 | }; 59 | 60 | 61 | static void 62 | ngx_rtmp_eval_append(ngx_buf_t *b, void *data, size_t len, ngx_log_t *log) 63 | { 64 | size_t buf_len; 65 | 66 | if (b->last + len > b->end) { 67 | buf_len = 2 * (b->last - b->pos) + len; 68 | 69 | b->start = ngx_alloc(buf_len, log); 70 | if (b->start == NULL) { 71 | return; 72 | } 73 | 74 | b->last = ngx_cpymem(b->start, b->pos, b->last - b->pos); 75 | b->pos = b->start; 76 | b->end = b->start + buf_len; 77 | } 78 | 79 | b->last = ngx_cpymem(b->last, data, len); 80 | } 81 | 82 | 83 | static void 84 | ngx_rtmp_eval_append_var(void *ctx, ngx_buf_t *b, ngx_rtmp_eval_t **e, 85 | ngx_str_t *name, ngx_log_t *log) 86 | { 87 | ngx_str_t v; 88 | ngx_rtmp_eval_t *ee; 89 | 90 | for (; *e; ++e) { 91 | for (ee = *e; ee->handler; ++ee) { 92 | if (ee->name.len == name->len && 93 | ngx_memcmp(ee->name.data, name->data, name->len) == 0) 94 | { 95 | ee->handler(ctx, ee, &v); 96 | ngx_rtmp_eval_append(b, v.data, v.len, log); 97 | } 98 | } 99 | } 100 | } 101 | 102 | 103 | ngx_int_t 104 | ngx_rtmp_eval(void *ctx, ngx_str_t *in, ngx_rtmp_eval_t **e, ngx_str_t *out, 105 | ngx_log_t *log) 106 | { 107 | u_char c, *p; 108 | ngx_str_t name; 109 | ngx_buf_t b; 110 | ngx_uint_t n; 111 | 112 | enum { 113 | NORMAL, 114 | ESCAPE, 115 | NAME, 116 | SNAME 117 | } state = NORMAL; 118 | 119 | b.pos = b.last = b.start = ngx_alloc(NGX_RTMP_EVAL_BUFLEN, log); 120 | if (b.pos == NULL) { 121 | return NGX_ERROR; 122 | } 123 | 124 | b.end = b.pos + NGX_RTMP_EVAL_BUFLEN; 125 | name.data = NULL; 126 | 127 | for (n = 0; n < in->len; ++n) { 128 | p = &in->data[n]; 129 | c = *p; 130 | 131 | switch (state) { 132 | case SNAME: 133 | if (c != '}') { 134 | continue; 135 | } 136 | 137 | name.len = p - name.data; 138 | ngx_rtmp_eval_append_var(ctx, &b, e, &name, log); 139 | 140 | state = NORMAL; 141 | 142 | continue; 143 | 144 | case NAME: 145 | if (c == '{' && name.data == p) { 146 | ++name.data; 147 | state = SNAME; 148 | continue; 149 | } 150 | if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { 151 | continue; 152 | } 153 | 154 | name.len = p - name.data; 155 | ngx_rtmp_eval_append_var(ctx, &b, e, &name, log); 156 | 157 | /* fall through */ 158 | 159 | case NORMAL: 160 | switch (c) { 161 | case '$': 162 | name.data = p + 1; 163 | state = NAME; 164 | continue; 165 | case '\\': 166 | state = ESCAPE; 167 | continue; 168 | default: 169 | break; 170 | } 171 | 172 | /* fall through */ 173 | 174 | case ESCAPE: 175 | ngx_rtmp_eval_append(&b, &c, 1, log); 176 | state = NORMAL; 177 | break; 178 | 179 | } 180 | } 181 | 182 | if (state == NAME) { 183 | p = &in->data[n]; 184 | name.len = p - name.data; 185 | ngx_rtmp_eval_append_var(ctx, &b, e, &name, log); 186 | } 187 | 188 | c = 0; 189 | ngx_rtmp_eval_append(&b, &c, 1, log); 190 | 191 | out->data = b.pos; 192 | out->len = b.last - b.pos - 1; 193 | 194 | return NGX_OK; 195 | } 196 | 197 | 198 | ngx_int_t 199 | ngx_rtmp_eval_streams(ngx_str_t *in) 200 | { 201 | #if !(NGX_WIN32) 202 | ngx_int_t mode, create, v, close_src; 203 | ngx_fd_t dst, src; 204 | u_char *path; 205 | 206 | path = in->data; 207 | 208 | while (*path >= '0' && *path <= '9') { 209 | path++; 210 | } 211 | 212 | switch ((char) *path) { 213 | 214 | case '>': 215 | 216 | v = (path == in->data ? 1 : ngx_atoi(in->data, path - in->data)); 217 | if (v == NGX_ERROR) { 218 | return NGX_ERROR; 219 | } 220 | 221 | dst = (ngx_fd_t) v; 222 | mode = NGX_FILE_WRONLY; 223 | create = NGX_FILE_TRUNCATE; 224 | path++; 225 | 226 | if (*path == (u_char) '>') { 227 | mode = NGX_FILE_APPEND; 228 | create = NGX_FILE_CREATE_OR_OPEN; 229 | path++; 230 | } 231 | 232 | break; 233 | 234 | case '<': 235 | 236 | v = (path == in->data ? 0 : ngx_atoi(in->data, path - in->data)); 237 | if (v == NGX_ERROR) { 238 | return NGX_ERROR; 239 | } 240 | 241 | dst = (ngx_fd_t) v; 242 | mode = NGX_FILE_RDONLY; 243 | create = NGX_FILE_OPEN; 244 | path++; 245 | 246 | break; 247 | 248 | default: 249 | 250 | return NGX_DONE; 251 | } 252 | 253 | if (*path == (u_char) '&') { 254 | 255 | path++; 256 | v = ngx_atoi(path, in->data + in->len - path); 257 | if (v == NGX_ERROR) { 258 | return NGX_ERROR; 259 | } 260 | src = (ngx_fd_t) v; 261 | close_src = 0; 262 | 263 | } else { 264 | 265 | src = ngx_open_file(path, mode, create, NGX_FILE_DEFAULT_ACCESS); 266 | if (src == NGX_INVALID_FILE) { 267 | return NGX_ERROR; 268 | } 269 | close_src = 1; 270 | 271 | } 272 | 273 | if (src == dst) { 274 | return NGX_OK; 275 | } 276 | 277 | dup2(src, dst); 278 | 279 | if (close_src) { 280 | ngx_close_file(src); 281 | } 282 | return NGX_OK; 283 | 284 | #else 285 | return NGX_DONE; 286 | #endif 287 | } 288 | -------------------------------------------------------------------------------- /config: -------------------------------------------------------------------------------- 1 | ngx_addon_name="ngx_http_flv_live_module" 2 | 3 | RTMP_CORE_MODULES=" \ 4 | ngx_rtmp_module \ 5 | ngx_rtmp_core_module \ 6 | ngx_rtmp_cmd_module \ 7 | ngx_rtmp_codec_module \ 8 | ngx_rtmp_access_module \ 9 | ngx_rtmp_record_module \ 10 | ngx_rtmp_gop_cache_module \ 11 | ngx_rtmp_live_module \ 12 | ngx_rtmp_flv_live_index_module \ 13 | ngx_rtmp_play_module \ 14 | ngx_rtmp_flv_module \ 15 | ngx_rtmp_mp4_module \ 16 | ngx_rtmp_netcall_module \ 17 | ngx_rtmp_relay_module \ 18 | ngx_rtmp_exec_module \ 19 | ngx_rtmp_auto_push_module \ 20 | ngx_rtmp_auto_push_index_module \ 21 | ngx_rtmp_log_module \ 22 | ngx_rtmp_limit_module \ 23 | ngx_rtmp_hls_module \ 24 | ngx_rtmp_dash_module \ 25 | ngx_rtmp_notify_module \ 26 | " 27 | 28 | 29 | RTMP_HTTP_MODULES=" \ 30 | ngx_rtmp_stat_module \ 31 | ngx_rtmp_control_module \ 32 | ngx_http_flv_live_module \ 33 | " 34 | 35 | 36 | RTMP_DEPS=" \ 37 | $ngx_addon_dir/ngx_rtmp_amf.h \ 38 | $ngx_addon_dir/ngx_rtmp_bandwidth.h \ 39 | $ngx_addon_dir/ngx_rtmp_cmd_module.h \ 40 | $ngx_addon_dir/ngx_rtmp_codec_module.h \ 41 | $ngx_addon_dir/ngx_rtmp_eval.h \ 42 | $ngx_addon_dir/ngx_rtmp.h \ 43 | $ngx_addon_dir/ngx_rtmp_version.h \ 44 | $ngx_addon_dir/ngx_rtmp_live_module.h \ 45 | $ngx_addon_dir/ngx_rtmp_netcall_module.h \ 46 | $ngx_addon_dir/ngx_rtmp_play_module.h \ 47 | $ngx_addon_dir/ngx_rtmp_record_module.h \ 48 | $ngx_addon_dir/ngx_rtmp_gop_cache_module.h \ 49 | $ngx_addon_dir/ngx_rtmp_relay_module.h \ 50 | $ngx_addon_dir/ngx_rtmp_streams.h \ 51 | $ngx_addon_dir/ngx_rtmp_bitop.h \ 52 | $ngx_addon_dir/ngx_rtmp_proxy_protocol.h \ 53 | $ngx_addon_dir/ngx_rtmp_variables.h \ 54 | $ngx_addon_dir/hls/ngx_rtmp_mpegts.h \ 55 | $ngx_addon_dir/hls/ngx_rtmp_mpegts_crc.h \ 56 | $ngx_addon_dir/dash/ngx_rtmp_mp4.h \ 57 | " 58 | 59 | 60 | RTMP_CORE_SRCS=" \ 61 | $ngx_addon_dir/ngx_rtmp.c \ 62 | $ngx_addon_dir/ngx_rtmp_init.c \ 63 | $ngx_addon_dir/ngx_rtmp_handshake.c \ 64 | $ngx_addon_dir/ngx_rtmp_handler.c \ 65 | $ngx_addon_dir/ngx_rtmp_amf.c \ 66 | $ngx_addon_dir/ngx_rtmp_send.c \ 67 | $ngx_addon_dir/ngx_rtmp_shared.c \ 68 | $ngx_addon_dir/ngx_rtmp_eval.c \ 69 | $ngx_addon_dir/ngx_rtmp_receive.c \ 70 | $ngx_addon_dir/ngx_rtmp_core_module.c \ 71 | $ngx_addon_dir/ngx_rtmp_cmd_module.c \ 72 | $ngx_addon_dir/ngx_rtmp_codec_module.c \ 73 | $ngx_addon_dir/ngx_rtmp_access_module.c \ 74 | $ngx_addon_dir/ngx_rtmp_record_module.c \ 75 | $ngx_addon_dir/ngx_rtmp_gop_cache_module.c \ 76 | $ngx_addon_dir/ngx_rtmp_live_module.c \ 77 | $ngx_addon_dir/ngx_rtmp_flv_live_index_module.c \ 78 | $ngx_addon_dir/ngx_rtmp_play_module.c \ 79 | $ngx_addon_dir/ngx_rtmp_flv_module.c \ 80 | $ngx_addon_dir/ngx_rtmp_mp4_module.c \ 81 | $ngx_addon_dir/ngx_rtmp_netcall_module.c \ 82 | $ngx_addon_dir/ngx_rtmp_relay_module.c \ 83 | $ngx_addon_dir/ngx_rtmp_bandwidth.c \ 84 | $ngx_addon_dir/ngx_rtmp_exec_module.c \ 85 | $ngx_addon_dir/ngx_rtmp_auto_push_module.c \ 86 | $ngx_addon_dir/ngx_rtmp_notify_module.c \ 87 | $ngx_addon_dir/ngx_rtmp_log_module.c \ 88 | $ngx_addon_dir/ngx_rtmp_limit_module.c \ 89 | $ngx_addon_dir/ngx_rtmp_bitop.c \ 90 | $ngx_addon_dir/ngx_rtmp_proxy_protocol.c \ 91 | $ngx_addon_dir/ngx_rtmp_variables.c \ 92 | $ngx_addon_dir/ngx_rtmp_parse.c \ 93 | $ngx_addon_dir/hls/ngx_rtmp_hls_module.c \ 94 | $ngx_addon_dir/dash/ngx_rtmp_dash_module.c \ 95 | $ngx_addon_dir/hls/ngx_rtmp_mpegts.c \ 96 | $ngx_addon_dir/hls/ngx_rtmp_mpegts_crc.c \ 97 | $ngx_addon_dir/dash/ngx_rtmp_mp4.c \ 98 | " 99 | 100 | 101 | RTMP_HTTP_DEPS=" \ 102 | $ngx_addon_dir/ngx_http_flv_live_module.h \ 103 | " 104 | 105 | 106 | RTMP_HTTP_SRCS=" \ 107 | $ngx_addon_dir/ngx_rtmp_stat_module.c \ 108 | $ngx_addon_dir/ngx_rtmp_control_module.c \ 109 | $ngx_addon_dir/ngx_http_flv_live_module.c \ 110 | " 111 | 112 | if [ -f auto/module ] ; then 113 | ngx_module_incs=$ngx_addon_dir 114 | ngx_module_deps="$RTMP_DEPS $RTMP_HTTP_DEPS" 115 | 116 | if [ $ngx_module_link = DYNAMIC ] ; then 117 | ngx_module_name="$ngx_addon_name $RTMP_CORE_MODULES $RTMP_HTTP_MODULES" 118 | ngx_module_srcs="$RTMP_CORE_SRCS $RTMP_HTTP_SRCS" 119 | 120 | . auto/module 121 | 122 | dynamic_modules=`eval echo '$'"${ngx_module}_MODULES" | sed -e "s/ \{0,\}$ngx_addon_name//"` 123 | eval ${ngx_module}_MODULES=\"$dynamic_modules\" 124 | unset dynamic_modules 125 | 126 | order_modules=`eval echo '$'"${ngx_module}_ORDER"` 127 | if [ -n "$order_modules" ] 128 | then 129 | eval ${ngx_module}_ORDER=\"`echo "$order_modules" | sed -e "s/ \{0,\}$ngx_addon_name//"`\" 130 | unset order_modules 131 | fi 132 | else 133 | ngx_module_type=CORE 134 | ngx_module_name=$RTMP_CORE_MODULES 135 | ngx_module_deps=$RTMP_DEPS 136 | ngx_module_srcs=$RTMP_CORE_SRCS 137 | 138 | . auto/module 139 | 140 | 141 | ngx_module_type=HTTP 142 | ngx_module_name=$RTMP_HTTP_MODULES 143 | ngx_module_deps=$RTMP_HTTP_DEPS 144 | ngx_module_srcs=$RTMP_HTTP_SRCS 145 | 146 | . auto/module 147 | fi 148 | 149 | else 150 | CORE_MODULES="$CORE_MODULES $RTMP_CORE_MODULES" 151 | HTTP_MODULES="$HTTP_MODULES $RTMP_HTTP_MODULES" 152 | 153 | NGX_ADDON_DEPS="$NGX_ADDON_DEPS $RTMP_DEPS $RTMP_HTTP_DEPS" 154 | NGX_ADDON_SRCS="$NGX_ADDON_SRCS $RTMP_CORE_SRCS $RTMP_HTTP_SRCS" 155 | 156 | CFLAGS="$CFLAGS -I$ngx_addon_dir" 157 | fi 158 | 159 | USE_OPENSSL=YES 160 | 161 | -------------------------------------------------------------------------------- /test/www/jwplayer_old/swfobject.js: -------------------------------------------------------------------------------- 1 | /* SWFObject v2.1 2 | Copyright (c) 2007-2008 Geoff Stearns, Michael Williams, and Bobby van der Sluis 3 | This software is released under the MIT License 4 | */ 5 | var swfobject=function(){var b="undefined",Q="object",n="Shockwave Flash",p="ShockwaveFlash.ShockwaveFlash",P="application/x-shockwave-flash",m="SWFObjectExprInst",j=window,K=document,T=navigator,o=[],N=[],i=[],d=[],J,Z=null,M=null,l=null,e=false,A=false;var h=function(){var v=typeof K.getElementById!=b&&typeof K.getElementsByTagName!=b&&typeof K.createElement!=b,AC=[0,0,0],x=null;if(typeof T.plugins!=b&&typeof T.plugins[n]==Q){x=T.plugins[n].description;if(x&&!(typeof T.mimeTypes!=b&&T.mimeTypes[P]&&!T.mimeTypes[P].enabledPlugin)){x=x.replace(/^.*\s+(\S+\s+\S+$)/,"$1");AC[0]=parseInt(x.replace(/^(.*)\..*$/,"$1"),10);AC[1]=parseInt(x.replace(/^.*\.(.*)\s.*$/,"$1"),10);AC[2]=/r/.test(x)?parseInt(x.replace(/^.*r(.*)$/,"$1"),10):0}}else{if(typeof j.ActiveXObject!=b){var y=null,AB=false;try{y=new ActiveXObject(p+".7")}catch(t){try{y=new ActiveXObject(p+".6");AC=[6,0,21];y.AllowScriptAccess="always"}catch(t){if(AC[0]==6){AB=true}}if(!AB){try{y=new ActiveXObject(p)}catch(t){}}}if(!AB&&y){try{x=y.GetVariable("$version");if(x){x=x.split(" ")[1].split(",");AC=[parseInt(x[0],10),parseInt(x[1],10),parseInt(x[2],10)]}}catch(t){}}}}var AD=T.userAgent.toLowerCase(),r=T.platform.toLowerCase(),AA=/webkit/.test(AD)?parseFloat(AD.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,q=false,z=r?/win/.test(r):/win/.test(AD),w=r?/mac/.test(r):/mac/.test(AD);/*@cc_on q=true;@if(@_win32)z=true;@elif(@_mac)w=true;@end@*/return{w3cdom:v,pv:AC,webkit:AA,ie:q,win:z,mac:w}}();var L=function(){if(!h.w3cdom){return }f(H);if(h.ie&&h.win){try{K.write("