1 
2 /*
3  * Copyright (C) Roman Arutyunyan
4  */
5 
6 
7 #ifndef _NGX_RTMP_H_INCLUDED_
8 #define _NGX_RTMP_H_INCLUDED_
9 
10 
11 #include <ngx_config.h>
12 #include <ngx_core.h>
13 #include <ngx_event.h>
14 #include <ngx_event_connect.h>
15 #include <nginx.h>
16 
17 #include "ngx_rtmp_amf.h"
18 #include "ngx_rtmp_bandwidth.h"
19 
20 
21 #if (NGX_WIN32)
22 typedef __int8              int8_t;
23 typedef unsigned __int8     uint8_t;
24 #endif
25 
26 
27 typedef struct {
28     void                  **main_conf;
29     void                  **srv_conf;
30     void                  **app_conf;
31 } ngx_rtmp_conf_ctx_t;
32 
33 
34 typedef struct {
35     u_char                  sockaddr[NGX_SOCKADDRLEN];
36     socklen_t               socklen;
37 
38     /* server ctx */
39     ngx_rtmp_conf_ctx_t    *ctx;
40 
41     unsigned                bind:1;
42     unsigned                wildcard:1;
43 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
44     unsigned                ipv6only:2;
45 #endif
46     unsigned                so_keepalive:2;
47     unsigned                proxy_protocol:1;
48 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
49     int                     tcp_keepidle;
50     int                     tcp_keepintvl;
51     int                     tcp_keepcnt;
52 #endif
53 } ngx_rtmp_listen_t;
54 
55 
56 typedef struct {
57     ngx_rtmp_conf_ctx_t    *ctx;
58     ngx_str_t               addr_text;
59     unsigned                proxy_protocol:1;
60 } ngx_rtmp_addr_conf_t;
61 
62 typedef struct {
63     ngx_rtmp_addr_conf_t    conf;
64     in_addr_t               addr;
65 } ngx_rtmp_in_addr_t;
66 
67 
68 #if (NGX_HAVE_INET6)
69 
70 typedef struct {
71     ngx_rtmp_addr_conf_t    conf;
72     struct in6_addr         addr6;
73 } ngx_rtmp_in6_addr_t;
74 
75 #endif
76 
77 
78 typedef struct {
79     void                   *addrs;
80     ngx_uint_t              naddrs;
81 } ngx_rtmp_port_t;
82 
83 
84 typedef struct {
85     int                     family;
86     in_port_t               port;
87     ngx_array_t             addrs;       /* array of ngx_rtmp_conf_addr_t */
88 } ngx_rtmp_conf_port_t;
89 
90 
91 typedef struct {
92     struct sockaddr        *sockaddr;
93     socklen_t               socklen;
94 
95     ngx_rtmp_conf_ctx_t    *ctx;
96 
97     unsigned                bind:1;
98     unsigned                wildcard:1;
99 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
100     unsigned                ipv6only:2;
101 #endif
102     unsigned                so_keepalive:2;
103     unsigned                proxy_protocol:1;
104 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
105     int                     tcp_keepidle;
106     int                     tcp_keepintvl;
107     int                     tcp_keepcnt;
108 #endif
109 } ngx_rtmp_conf_addr_t;
110 
111 
112 #define NGX_RTMP_VERSION                3
113 
114 #define NGX_LOG_DEBUG_RTMP              NGX_LOG_DEBUG_CORE
115 
116 #define NGX_RTMP_DEFAULT_CHUNK_SIZE     128
117 
118 
119 /* RTMP message types */
120 #define NGX_RTMP_MSG_CHUNK_SIZE         1
121 #define NGX_RTMP_MSG_ABORT              2
122 #define NGX_RTMP_MSG_ACK                3
123 #define NGX_RTMP_MSG_USER               4
124 #define NGX_RTMP_MSG_ACK_SIZE           5
125 #define NGX_RTMP_MSG_BANDWIDTH          6
126 #define NGX_RTMP_MSG_EDGE               7
127 #define NGX_RTMP_MSG_AUDIO              8
128 #define NGX_RTMP_MSG_VIDEO              9
129 #define NGX_RTMP_MSG_AMF3_META          15
130 #define NGX_RTMP_MSG_AMF3_SHARED        16
131 #define NGX_RTMP_MSG_AMF3_CMD           17
132 #define NGX_RTMP_MSG_AMF_META           18
133 #define NGX_RTMP_MSG_AMF_SHARED         19
134 #define NGX_RTMP_MSG_AMF_CMD            20
135 #define NGX_RTMP_MSG_AGGREGATE          22
136 #define NGX_RTMP_MSG_MAX                22
137 
138 #define NGX_RTMP_CONNECT                NGX_RTMP_MSG_MAX + 1
139 #define NGX_RTMP_DISCONNECT             NGX_RTMP_MSG_MAX + 2
140 #define NGX_RTMP_HANDSHAKE_DONE         NGX_RTMP_MSG_MAX + 3
141 #define NGX_RTMP_MAX_EVENT              NGX_RTMP_MSG_MAX + 4
142 
143 
144 /* RMTP control message types */
145 #define NGX_RTMP_USER_STREAM_BEGIN      0
146 #define NGX_RTMP_USER_STREAM_EOF        1
147 #define NGX_RTMP_USER_STREAM_DRY        2
148 #define NGX_RTMP_USER_SET_BUFLEN        3
149 #define NGX_RTMP_USER_RECORDED          4
150 #define NGX_RTMP_USER_PING_REQUEST      6
151 #define NGX_RTMP_USER_PING_RESPONSE     7
152 #define NGX_RTMP_USER_UNKNOWN           8
153 #define NGX_RTMP_USER_BUFFER_END        31
154 
155 
156 /* Chunk header:
157  *   max 3  basic header
158  * + max 11 message header
159  * + max 4  extended header (timestamp) */
160 #define NGX_RTMP_MAX_CHUNK_HEADER       18
161 
162 
163 typedef struct {
164     uint32_t                csid;       /* chunk stream id */
165     uint32_t                timestamp;  /* timestamp (delta) */
166     uint32_t                mlen;       /* message length */
167     uint8_t                 type;       /* message type id */
168     uint32_t                msid;       /* message stream id */
169 } ngx_rtmp_header_t;
170 
171 
172 typedef struct {
173     ngx_rtmp_header_t       hdr;
174     uint32_t                dtime;
175     uint32_t                len;        /* current fragment length */
176     uint8_t                 ext;
177     ngx_chain_t            *in;
178 } ngx_rtmp_stream_t;
179 
180 
181 /* disable zero-sized array warning by msvc */
182 
183 #if (NGX_WIN32)
184 #pragma warning(push)
185 #pragma warning(disable:4200)
186 #endif
187 
188 
189 typedef struct {
190     uint32_t                signature;  /* "RTMP" */ /* <-- FIXME wtf */
191 
192     ngx_event_t             close;
193 
194     void                  **ctx;
195     void                  **main_conf;
196     void                  **srv_conf;
197     void                  **app_conf;
198 
199     ngx_str_t              *addr_text;
200     int                     connected;
201 
202 #if (nginx_version >= 1007005)
203     ngx_queue_t             posted_dry_events;
204 #else
205     ngx_event_t            *posted_dry_events;
206 #endif
207 
208     /* client buffer time in msec */
209     uint32_t                buflen;
210     uint32_t                ack_size;
211 
212     /* connection parameters */
213     ngx_str_t               app;
214     ngx_str_t               args;
215     ngx_str_t               flashver;
216     ngx_str_t               swf_url;
217     ngx_str_t               tc_url;
218     uint32_t                acodecs;
219     uint32_t                vcodecs;
220     ngx_str_t               page_url;
221 
222     /* handshake data */
223     ngx_buf_t              *hs_buf;
224     u_char                 *hs_digest;
225     unsigned                hs_old:1;
226     ngx_uint_t              hs_stage;
227 
228     /* connection timestamps */
229     ngx_msec_t              epoch;
230     ngx_msec_t              peer_epoch;
231     ngx_msec_t              base_time;
232     uint32_t                current_time;
233 
234     /* ready for publishing? */
235     unsigned                ready_for_publish:1;
236 
237     /* ping */
238     ngx_event_t             ping_evt;
239     unsigned                ping_active:1;
240     unsigned                ping_reset:1;
241 
242     /* auto-pushed? */
243     unsigned                auto_pushed:1;
244     unsigned                relay:1;
245     unsigned                static_relay:1;
246 
247     /* input stream 0 (reserved by RTMP spec)
248      * is used as free chain link */
249 
250     ngx_rtmp_stream_t      *in_streams;
251     uint32_t                in_csid;
252     ngx_uint_t              in_chunk_size;
253     ngx_pool_t             *in_pool;
254     uint32_t                in_bytes;
255     uint32_t                in_last_ack;
256 
257     ngx_pool_t             *in_old_pool;
258     ngx_int_t               in_chunk_size_changing;
259 
260     ngx_connection_t       *connection;
261 
262     /* circular buffer of RTMP message pointers */
263     ngx_msec_t              timeout;
264     uint32_t                out_bytes;
265     size_t                  out_pos, out_last;
266     ngx_chain_t            *out_chain;
267     u_char                 *out_bpos;
268     unsigned                out_buffer:1;
269     size_t                  out_queue;
270     size_t                  out_cork;
271     ngx_chain_t            *out[0];
272 } ngx_rtmp_session_t;
273 
274 
275 #if (NGX_WIN32)
276 #pragma warning(pop)
277 #endif
278 
279 
280 /* handler result code:
281  *  NGX_ERROR - error
282  *  NGX_OK    - success, may continue
283  *  NGX_DONE  - success, input parsed, reply sent; need no
284  *      more calls on this event */
285 typedef ngx_int_t (*ngx_rtmp_handler_pt)(ngx_rtmp_session_t *s,
286         ngx_rtmp_header_t *h, ngx_chain_t *in);
287 
288 
289 typedef struct {
290     ngx_str_t               name;
291     ngx_rtmp_handler_pt     handler;
292 } ngx_rtmp_amf_handler_t;
293 
294 
295 typedef struct {
296     ngx_array_t             servers;    /* ngx_rtmp_core_srv_conf_t */
297     ngx_array_t             listen;     /* ngx_rtmp_listen_t */
298 
299     ngx_array_t             events[NGX_RTMP_MAX_EVENT];
300 
301     ngx_hash_t              amf_hash;
302     ngx_array_t             amf_arrays;
303     ngx_array_t             amf;
304 } ngx_rtmp_core_main_conf_t;
305 
306 
307 /* global main conf for stats */
308 extern ngx_rtmp_core_main_conf_t   *ngx_rtmp_core_main_conf;
309 
310 
311 typedef struct ngx_rtmp_core_srv_conf_s {
312     ngx_array_t             applications; /* ngx_rtmp_core_app_conf_t */
313 
314     ngx_msec_t              timeout;
315     ngx_msec_t              ping;
316     ngx_msec_t              ping_timeout;
317     ngx_flag_t              so_keepalive;
318     ngx_int_t               max_streams;
319 
320     ngx_uint_t              ack_window;
321 
322     ngx_int_t               chunk_size;
323     ngx_pool_t             *pool;
324     ngx_chain_t            *free;
325     ngx_chain_t            *free_hs;
326     size_t                  max_message;
327     ngx_flag_t              play_time_fix;
328     ngx_flag_t              publish_time_fix;
329     ngx_flag_t              busy;
330     size_t                  out_queue;
331     size_t                  out_cork;
332     ngx_msec_t              buflen;
333 
334     ngx_rtmp_conf_ctx_t    *ctx;
335 } ngx_rtmp_core_srv_conf_t;
336 
337 
338 typedef struct {
339     ngx_array_t             applications; /* ngx_rtmp_core_app_conf_t */
340     ngx_str_t               name;
341     void                  **app_conf;
342 } ngx_rtmp_core_app_conf_t;
343 
344 
345 typedef struct {
346     ngx_str_t              *client;
347     ngx_rtmp_session_t     *session;
348 } ngx_rtmp_error_log_ctx_t;
349 
350 
351 typedef struct {
352     ngx_int_t             (*preconfiguration)(ngx_conf_t *cf);
353     ngx_int_t             (*postconfiguration)(ngx_conf_t *cf);
354 
355     void                 *(*create_main_conf)(ngx_conf_t *cf);
356     char                 *(*init_main_conf)(ngx_conf_t *cf, void *conf);
357 
358     void                 *(*create_srv_conf)(ngx_conf_t *cf);
359     char                 *(*merge_srv_conf)(ngx_conf_t *cf, void *prev,
360                                     void *conf);
361 
362     void                 *(*create_app_conf)(ngx_conf_t *cf);
363     char                 *(*merge_app_conf)(ngx_conf_t *cf, void *prev,
364                                     void *conf);
365 } ngx_rtmp_module_t;
366 
367 #define NGX_RTMP_MODULE                 0x504D5452     /* "RTMP" */
368 
369 #define NGX_RTMP_MAIN_CONF              0x02000000
370 #define NGX_RTMP_SRV_CONF               0x04000000
371 #define NGX_RTMP_APP_CONF               0x08000000
372 #define NGX_RTMP_REC_CONF               0x10000000
373 
374 
375 #define NGX_RTMP_MAIN_CONF_OFFSET  offsetof(ngx_rtmp_conf_ctx_t, main_conf)
376 #define NGX_RTMP_SRV_CONF_OFFSET   offsetof(ngx_rtmp_conf_ctx_t, srv_conf)
377 #define NGX_RTMP_APP_CONF_OFFSET   offsetof(ngx_rtmp_conf_ctx_t, app_conf)
378 
379 
380 #define ngx_rtmp_get_module_ctx(s, module)     (s)->ctx[module.ctx_index]
381 #define ngx_rtmp_set_ctx(s, c, module)         s->ctx[module.ctx_index] = c;
382 #define ngx_rtmp_delete_ctx(s, module)         s->ctx[module.ctx_index] = NULL;
383 
384 
385 #define ngx_rtmp_get_module_main_conf(s, module)                             \
386     (s)->main_conf[module.ctx_index]
387 #define ngx_rtmp_get_module_srv_conf(s, module)  (s)->srv_conf[module.ctx_index]
388 #define ngx_rtmp_get_module_app_conf(s, module)  ((s)->app_conf ? \
389     (s)->app_conf[module.ctx_index] : NULL)
390 
391 #define ngx_rtmp_conf_get_module_main_conf(cf, module)                       \
392     ((ngx_rtmp_conf_ctx_t *) cf->ctx)->main_conf[module.ctx_index]
393 #define ngx_rtmp_conf_get_module_srv_conf(cf, module)                        \
394     ((ngx_rtmp_conf_ctx_t *) cf->ctx)->srv_conf[module.ctx_index]
395 #define ngx_rtmp_conf_get_module_app_conf(cf, module)                        \
396     ((ngx_rtmp_conf_ctx_t *) cf->ctx)->app_conf[module.ctx_index]
397 
398 
399 #ifdef NGX_DEBUG
400 char* ngx_rtmp_message_type(uint8_t type);
401 char* ngx_rtmp_user_message_type(uint16_t evt);
402 #endif
403 
404 void ngx_rtmp_init_connection(ngx_connection_t *c);
405 ngx_rtmp_session_t * ngx_rtmp_init_session(ngx_connection_t *c,
406      ngx_rtmp_addr_conf_t *addr_conf);
407 void ngx_rtmp_finalize_session(ngx_rtmp_session_t *s);
408 void ngx_rtmp_handshake(ngx_rtmp_session_t *s);
409 void ngx_rtmp_client_handshake(ngx_rtmp_session_t *s, unsigned async);
410 void ngx_rtmp_free_handshake_buffers(ngx_rtmp_session_t *s);
411 void ngx_rtmp_cycle(ngx_rtmp_session_t *s);
412 void ngx_rtmp_reset_ping(ngx_rtmp_session_t *s);
413 ngx_int_t ngx_rtmp_fire_event(ngx_rtmp_session_t *s, ngx_uint_t evt,
414         ngx_rtmp_header_t *h, ngx_chain_t *in);
415 
416 
417 ngx_int_t ngx_rtmp_set_chunk_size(ngx_rtmp_session_t *s, ngx_uint_t size);
418 
419 
420 /* Bit reverse: we need big-endians in many places  */
421 void * ngx_rtmp_rmemcpy(void *dst, const void* src, size_t n);
422 
423 #define ngx_rtmp_rcpymem(dst, src, n) \
424     (((u_char*)ngx_rtmp_rmemcpy(dst, src, n)) + (n))
425 
426 
427 static ngx_inline uint16_t
ngx_rtmp_r16(uint16_t n)428 ngx_rtmp_r16(uint16_t n)
429 {
430     return (n << 8) | (n >> 8);
431 }
432 
433 
434 static ngx_inline uint32_t
ngx_rtmp_r32(uint32_t n)435 ngx_rtmp_r32(uint32_t n)
436 {
437     return (n << 24) | ((n << 8) & 0xff0000) | ((n >> 8) & 0xff00) | (n >> 24);
438 }
439 
440 
441 static ngx_inline uint64_t
ngx_rtmp_r64(uint64_t n)442 ngx_rtmp_r64(uint64_t n)
443 {
444     return (uint64_t) ngx_rtmp_r32((uint32_t) n) << 32 |
445                       ngx_rtmp_r32((uint32_t) (n >> 32));
446 }
447 
448 
449 /* Receiving messages */
450 ngx_int_t ngx_rtmp_receive_message(ngx_rtmp_session_t *s,
451         ngx_rtmp_header_t *h, ngx_chain_t *in);
452 ngx_int_t ngx_rtmp_protocol_message_handler(ngx_rtmp_session_t *s,
453         ngx_rtmp_header_t *h, ngx_chain_t *in);
454 ngx_int_t ngx_rtmp_user_message_handler(ngx_rtmp_session_t *s,
455         ngx_rtmp_header_t *h, ngx_chain_t *in);
456 ngx_int_t ngx_rtmp_aggregate_message_handler(ngx_rtmp_session_t *s,
457         ngx_rtmp_header_t *h, ngx_chain_t *in);
458 ngx_int_t ngx_rtmp_amf_message_handler(ngx_rtmp_session_t *s,
459         ngx_rtmp_header_t *h, ngx_chain_t *in);
460 ngx_int_t ngx_rtmp_amf_shared_object_handler(ngx_rtmp_session_t *s,
461         ngx_rtmp_header_t *h, ngx_chain_t *in);
462 
463 
464 /* Shared output buffers */
465 
466 /* Store refcount in negative bytes of shared buffer */
467 
468 #define NGX_RTMP_REFCOUNT_TYPE              uint32_t
469 #define NGX_RTMP_REFCOUNT_BYTES             sizeof(NGX_RTMP_REFCOUNT_TYPE)
470 
471 #define ngx_rtmp_ref(b)                     \
472     *((NGX_RTMP_REFCOUNT_TYPE*)(b) - 1)
473 
474 #define ngx_rtmp_ref_set(b, v)              \
475     ngx_rtmp_ref(b) = v
476 
477 #define ngx_rtmp_ref_get(b)                 \
478     ++ngx_rtmp_ref(b)
479 
480 #define ngx_rtmp_ref_put(b)                 \
481     --ngx_rtmp_ref(b)
482 
483 ngx_chain_t * ngx_rtmp_alloc_shared_buf(ngx_rtmp_core_srv_conf_t *cscf);
484 void ngx_rtmp_free_shared_chain(ngx_rtmp_core_srv_conf_t *cscf,
485         ngx_chain_t *in);
486 ngx_chain_t * ngx_rtmp_append_shared_bufs(ngx_rtmp_core_srv_conf_t *cscf,
487         ngx_chain_t *head, ngx_chain_t *in);
488 
489 #define ngx_rtmp_acquire_shared_chain(in)   \
490     ngx_rtmp_ref_get(in);                   \
491 
492 
493 /* Sending messages */
494 void ngx_rtmp_prepare_message(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
495         ngx_rtmp_header_t *lh, ngx_chain_t *out);
496 ngx_int_t ngx_rtmp_send_message(ngx_rtmp_session_t *s, ngx_chain_t *out,
497         ngx_uint_t priority);
498 
499 /* Note on priorities:
500  * the bigger value the lower the priority.
501  * priority=0 is the highest */
502 
503 
504 #define NGX_RTMP_LIMIT_SOFT         0
505 #define NGX_RTMP_LIMIT_HARD         1
506 #define NGX_RTMP_LIMIT_DYNAMIC      2
507 
508 /* Protocol control messages */
509 ngx_chain_t * ngx_rtmp_create_chunk_size(ngx_rtmp_session_t *s,
510         uint32_t chunk_size);
511 ngx_chain_t * ngx_rtmp_create_abort(ngx_rtmp_session_t *s,
512         uint32_t csid);
513 ngx_chain_t * ngx_rtmp_create_ack(ngx_rtmp_session_t *s,
514         uint32_t seq);
515 ngx_chain_t * ngx_rtmp_create_ack_size(ngx_rtmp_session_t *s,
516         uint32_t ack_size);
517 ngx_chain_t * ngx_rtmp_create_bandwidth(ngx_rtmp_session_t *s,
518         uint32_t ack_size, uint8_t limit_type);
519 
520 ngx_int_t ngx_rtmp_send_chunk_size(ngx_rtmp_session_t *s,
521         uint32_t chunk_size);
522 ngx_int_t ngx_rtmp_send_abort(ngx_rtmp_session_t *s,
523         uint32_t csid);
524 ngx_int_t ngx_rtmp_send_ack(ngx_rtmp_session_t *s,
525         uint32_t seq);
526 ngx_int_t ngx_rtmp_send_ack_size(ngx_rtmp_session_t *s,
527         uint32_t ack_size);
528 ngx_int_t ngx_rtmp_send_bandwidth(ngx_rtmp_session_t *s,
529         uint32_t ack_size, uint8_t limit_type);
530 
531 /* User control messages */
532 ngx_chain_t * ngx_rtmp_create_stream_begin(ngx_rtmp_session_t *s,
533         uint32_t msid);
534 ngx_chain_t * ngx_rtmp_create_stream_eof(ngx_rtmp_session_t *s,
535         uint32_t msid);
536 ngx_chain_t * ngx_rtmp_create_stream_dry(ngx_rtmp_session_t *s,
537         uint32_t msid);
538 ngx_chain_t * ngx_rtmp_create_set_buflen(ngx_rtmp_session_t *s,
539         uint32_t msid, uint32_t buflen_msec);
540 ngx_chain_t * ngx_rtmp_create_recorded(ngx_rtmp_session_t *s,
541         uint32_t msid);
542 ngx_chain_t * ngx_rtmp_create_ping_request(ngx_rtmp_session_t *s,
543         uint32_t timestamp);
544 ngx_chain_t * ngx_rtmp_create_ping_response(ngx_rtmp_session_t *s,
545         uint32_t timestamp);
546 
547 ngx_int_t ngx_rtmp_send_stream_begin(ngx_rtmp_session_t *s,
548         uint32_t msid);
549 ngx_int_t ngx_rtmp_send_stream_eof(ngx_rtmp_session_t *s,
550         uint32_t msid);
551 ngx_int_t ngx_rtmp_send_stream_dry(ngx_rtmp_session_t *s,
552         uint32_t msid);
553 ngx_int_t ngx_rtmp_send_set_buflen(ngx_rtmp_session_t *s,
554         uint32_t msid, uint32_t buflen_msec);
555 ngx_int_t ngx_rtmp_send_recorded(ngx_rtmp_session_t *s,
556         uint32_t msid);
557 ngx_int_t ngx_rtmp_send_ping_request(ngx_rtmp_session_t *s,
558         uint32_t timestamp);
559 ngx_int_t ngx_rtmp_send_ping_response(ngx_rtmp_session_t *s,
560         uint32_t timestamp);
561 
562 /* AMF sender/receiver */
563 ngx_int_t ngx_rtmp_append_amf(ngx_rtmp_session_t *s,
564         ngx_chain_t **first, ngx_chain_t **last,
565         ngx_rtmp_amf_elt_t *elts, size_t nelts);
566 ngx_int_t ngx_rtmp_receive_amf(ngx_rtmp_session_t *s, ngx_chain_t *in,
567         ngx_rtmp_amf_elt_t *elts, size_t nelts);
568 
569 ngx_chain_t * ngx_rtmp_create_amf(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
570         ngx_rtmp_amf_elt_t *elts, size_t nelts);
571 ngx_int_t ngx_rtmp_send_amf(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
572         ngx_rtmp_amf_elt_t *elts, size_t nelts);
573 
574 /* AMF status sender */
575 ngx_chain_t * ngx_rtmp_create_status(ngx_rtmp_session_t *s, char *code,
576         char* level, char *desc);
577 ngx_chain_t * ngx_rtmp_create_play_status(ngx_rtmp_session_t *s, char *code,
578         char* level, ngx_uint_t duration, ngx_uint_t bytes);
579 ngx_chain_t * ngx_rtmp_create_sample_access(ngx_rtmp_session_t *s);
580 
581 ngx_int_t ngx_rtmp_send_status(ngx_rtmp_session_t *s, char *code,
582         char* level, char *desc);
583 ngx_int_t ngx_rtmp_send_play_status(ngx_rtmp_session_t *s, char *code,
584         char* level, ngx_uint_t duration, ngx_uint_t bytes);
585 ngx_int_t ngx_rtmp_send_sample_access(ngx_rtmp_session_t *s);
586 ngx_int_t ngx_rtmp_send_redirect_status(ngx_rtmp_session_t *s,
587         char *callMethod, char *desc, ngx_str_t to_url);
588 ngx_int_t ngx_rtmp_send_close_method(ngx_rtmp_session_t *s, char *methodName);
589 ngx_int_t ngx_rtmp_send_fcpublish(ngx_rtmp_session_t *s, u_char *desc);
590 ngx_int_t ngx_rtmp_send_fcunpublish(ngx_rtmp_session_t *s, u_char *desc);
591 ngx_int_t ngx_rtmp_send_fi(ngx_rtmp_session_t *s);
592 
593 
594 /* Frame types */
595 #define NGX_RTMP_VIDEO_KEY_FRAME            1
596 #define NGX_RTMP_VIDEO_INTER_FRAME          2
597 #define NGX_RTMP_VIDEO_DISPOSABLE_FRAME     3
598 
599 
600 static ngx_inline ngx_int_t
ngx_rtmp_get_video_frame_type(ngx_chain_t * in)601 ngx_rtmp_get_video_frame_type(ngx_chain_t *in)
602 {
603     return (in->buf->pos[0] & 0xf0) >> 4;
604 }
605 
606 
607 static ngx_inline ngx_int_t
ngx_rtmp_is_codec_header(ngx_chain_t * in)608 ngx_rtmp_is_codec_header(ngx_chain_t *in)
609 {
610     return in->buf->pos + 1 < in->buf->last && in->buf->pos[1] == 0;
611 }
612 
613 
614 extern ngx_rtmp_bandwidth_t                 ngx_rtmp_bw_out;
615 extern ngx_rtmp_bandwidth_t                 ngx_rtmp_bw_in;
616 
617 
618 extern ngx_uint_t                           ngx_rtmp_naccepted;
619 #if (nginx_version >= 1007011)
620 extern ngx_queue_t                          ngx_rtmp_init_queue;
621 #elif (nginx_version >= 1007005)
622 extern ngx_thread_volatile ngx_queue_t      ngx_rtmp_init_queue;
623 #else
624 extern ngx_thread_volatile ngx_event_t     *ngx_rtmp_init_queue;
625 #endif
626 
627 extern ngx_uint_t                           ngx_rtmp_max_module;
628 extern ngx_module_t                         ngx_rtmp_core_module;
629 
630 
631 #endif /* _NGX_RTMP_H_INCLUDED_ */
632