moved handling AVC/AAC headers to a separate code_module

This commit is contained in:
Roman Arutyunyan 2012-06-09 19:22:18 +04:00
parent 7c13597508
commit cc1e4899cc
9 changed files with 422 additions and 201 deletions

3
config
View file

@ -11,6 +11,7 @@ CORE_MODULES="$CORE_MODULES
ngx_rtmp_notify_module \
ngx_rtmp_relay_module \
ngx_rtmp_exec_module \
ngx_rtmp_codec_module \
"
@ -38,8 +39,8 @@ NGX_ADDON_SRCS="$NGX_ADDON_SRCS \
$ngx_addon_dir/ngx_rtmp_stat_module.c \
$ngx_addon_dir/ngx_rtmp_relay_module.c \
$ngx_addon_dir/ngx_rtmp_bandwidth.c \
$ngx_addon_dir/ngx_rtmp_codecs.c \
$ngx_addon_dir/ngx_rtmp_exec_module.c \
$ngx_addon_dir/ngx_rtmp_codec_module.c \
"
CFLAGS="$CFLAGS -I$ngx_addon_dir"

212
ngx_rtmp_codec_module.c Normal file
View file

@ -0,0 +1,212 @@
/*
* Copyright (c) 2012 Roman Arutyunyan
*/
#include "ngx_rtmp_codec_module.h"
#include "ngx_rtmp_live_module.h"
#include "ngx_rtmp_cmd_module.h"
static ngx_int_t ngx_rtmp_codec_postconfiguration(ngx_conf_t *cf);
static ngx_rtmp_module_t ngx_rtmp_codec_module_ctx = {
NULL, /* preconfiguration */
ngx_rtmp_codec_postconfiguration, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create app configuration */
NULL /* merge app configuration */
};
ngx_module_t ngx_rtmp_codec_module = {
NGX_MODULE_V1,
&ngx_rtmp_codec_module_ctx, /* module context */
NULL, /* module directives */
NGX_RTMP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static const char *
audio_codecs[] = {
"",
"ADPCM",
"MP3",
"LinearLE",
"Nellymoser16",
"Nellymoser8",
"Nellymoser",
"G711A",
"G711U",
"",
"AAC",
"Speex",
"",
"",
"MP3-8K",
"DeviceSpecific",
"Uncompressed"
};
static const char *
video_codecs[] = {
"",
"Jpeg",
"Sorenson-H263",
"ScreenVideo",
"On2-VP6",
"On2-VP6-Alpha",
"ScreenVideo2",
"H264",
};
u_char *
ngx_rtmp_get_audio_codec_name(ngx_uint_t id)
{
return (u_char *)(id < sizeof(audio_codecs) / sizeof(audio_codecs[0])
? audio_codecs[id]
: "");
}
u_char *
ngx_rtmp_get_video_codec_name(ngx_uint_t id)
{
return (u_char *)(id < sizeof(video_codecs) / sizeof(video_codecs[0])
? video_codecs[id]
: "");
}
static ngx_int_t
ngx_rtmp_codec_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_codec_ctx_t *ctx;
ngx_rtmp_core_srv_conf_t *cscf;
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
if (ctx == NULL) {
return NGX_OK;
}
cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
if (ctx->avc_header) {
ngx_rtmp_free_shared_chain(cscf, ctx->avc_header);
ctx->avc_header = NULL;
}
if (ctx->aac_header) {
ngx_rtmp_free_shared_chain(cscf, ctx->aac_header);
ctx->aac_header = NULL;
}
return NGX_OK;
}
static ngx_int_t
ngx_rtmp_codec_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_core_srv_conf_t *cscf;
ngx_rtmp_codec_ctx_t *ctx;
ngx_chain_t **header;
uint8_t fmt;
ngx_rtmp_header_t ch, lh;
/* save AVC/AAC header */
if ((h->type != NGX_RTMP_MSG_AUDIO
&& h->type != NGX_RTMP_MSG_VIDEO)
|| in->buf->last - in->buf->pos < 2)
{
return NGX_OK;
}
/* no conf */
if (in->buf->pos[1]) {
return NGX_OK;
}
cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module);
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
if (ctx == NULL) {
ctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_rtmp_codec_ctx_t));
ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_codec_module);
}
fmt = in->buf->pos[0];
header = NULL;
if (h->type == NGX_RTMP_MSG_AUDIO) {
if (((fmt & 0xf0) >> 4) == NGX_RTMP_AUDIO_AAC) {
header = &ctx->aac_header;
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"codec: AAC header arrived");
}
} else {
if ((fmt & 0x0f) == NGX_RTMP_VIDEO_H264) {
header = &ctx->avc_header;
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"codec: AVC/H264 header arrived");
}
}
if (header == NULL) {
return NGX_OK;
}
if (*header) {
ngx_rtmp_free_shared_chain(cscf, *header);
}
/* equal headers; timeout diff is zero */
ngx_memzero(&ch, sizeof(ch));
ngx_memzero(&lh, sizeof(lh));
ch.timestamp = h->timestamp;
ch.msid = NGX_RTMP_LIVE_MSID;
ch.type = h->type;
ch.csid = (h->type == NGX_RTMP_MSG_VIDEO
? NGX_RTMP_LIVE_CSID_VIDEO
: NGX_RTMP_LIVE_CSID_AUDIO);
lh = ch;
*header = ngx_rtmp_append_shared_bufs(cscf, NULL, in);
ngx_rtmp_prepare_message(s, &ch, &lh, *header);
return NGX_OK;
}
static ngx_int_t
ngx_rtmp_codec_postconfiguration(ngx_conf_t *cf)
{
ngx_rtmp_core_main_conf_t *cmcf;
ngx_rtmp_handler_pt *h;
cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module);
h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AUDIO]);
*h = ngx_rtmp_codec_av;
h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_VIDEO]);
*h = ngx_rtmp_codec_av;
h = ngx_array_push(&cmcf->events[NGX_RTMP_DISCONNECT]);
*h = ngx_rtmp_codec_disconnect;
return NGX_OK;
}

58
ngx_rtmp_codec_module.h Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2012 Roman Arutyunyan
*/
#ifndef _NGX_RTMP_CODEC_H_INCLUDED_
#define _NGX_RTMP_CODEC_H_INCLUDED_
#include "ngx_rtmp.h"
/* Audio codecs */
enum {
/* Uncompressed codec id is actually 0,
* but we use another value for consistency */
NGX_RTMP_AUDIO_UNCOMPRESSED = 16,
NGX_RTMP_AUDIO_ADPCM = 1,
NGX_RTMP_AUDIO_MP3 = 2,
NGX_RTMP_AUDIO_LINEAR_LE = 3,
NGX_RTMP_AUDIO_NELLY16 = 4,
NGX_RTMP_AUDIO_NELLY8 = 5,
NGX_RTMP_AUDIO_NELLY = 6,
NGX_RTMP_AUDIO_G711A = 7,
NGX_RTMP_AUDIO_G711U = 8,
NGX_RTMP_AUDIO_AAC = 10,
NGX_RTMP_AUDIO_SPEEX = 11,
NGX_RTMP_AUDIO_MP3_8 = 14,
NGX_RTMP_AUDIO_DEVSPEC = 15,
};
/* Video codecs */
enum {
NGX_RTMP_VIDEO_JPEG = 1,
NGX_RTMP_VIDEO_SORENSON_H263 = 2,
NGX_RTMP_VIDEO_SCREEN = 3,
NGX_RTMP_VIDEO_ON2_VP6 = 4,
NGX_RTMP_VIDEO_ON2_VP6_ALPHA = 5,
NGX_RTMP_VIDEO_SCREEN2 = 6,
NGX_RTMP_VIDEO_H264 = 7
};
u_char * ngx_rtmp_get_audio_codec_name(ngx_uint_t id);
u_char * ngx_rtmp_get_video_codec_name(ngx_uint_t id);
typedef struct {
ngx_chain_t *avc_header;
ngx_chain_t *aac_header;
} ngx_rtmp_codec_ctx_t;
extern ngx_module_t ngx_rtmp_codec_module;
#endif /* _NGX_RTMP_LIVE_H_INCLUDED_ */

View file

@ -1,57 +0,0 @@
/*
* Copyright (c) 2012 Roman Arutyunyan
*/
#include "ngx_rtmp_codecs.h"
const char * audio_codecs[] = {
"",
"ADPCM",
"MP3",
"LinearLE",
"Nellymoser16",
"Nellymoser8",
"Nellymoser",
"G711A",
"G711U",
"",
"AAC",
"Speex",
"",
"",
"MP3-8K",
"DeviceSpecific",
"Uncompressed"
};
const char * video_codecs[] = {
"",
"Jpeg",
"Sorenson-H263",
"ScreenVideo",
"On2-VP6",
"On2-VP6-Alpha",
"ScreenVideo2",
"H264",
};
u_char *
ngx_rtmp_get_audio_codec_name(ngx_uint_t id)
{
return (u_char *)(id < sizeof(audio_codecs) / sizeof(audio_codecs[0])
? audio_codecs[id]
: "");
}
u_char *
ngx_rtmp_get_video_codec_name(ngx_uint_t id)
{
return (u_char *)(id < sizeof(video_codecs) / sizeof(video_codecs[0])
? video_codecs[id]
: "");
}

View file

@ -1,42 +0,0 @@
/*
* Copyright (c) 2012 Roman Arutyunyan
*/
#ifndef _NGX_RTMP_CODECS_H_INCLUDED_
#define _NGX_RTMP_CODECS_H_INCLUDED_
#include <ngx_core.h>
/* Audio codecs */
enum {
/* Uncompressed codec id is actually 0,
* but we use another value for consistency */
NGX_RTMP_AUDIO_UNCOMPRESSED = 12,
NGX_RTMP_AUDIO_ADPCM = 1,
NGX_RTMP_AUDIO_MP3 = 2,
NGX_RTMP_AUDIO_NELLY8 = 5,
NGX_RTMP_AUDIO_NELLY = 6,
NGX_RTMP_AUDIO_HE_ACC = 10,
NGX_RTMP_AUDIO_SPEEX = 11
};
/* Video codecs */
enum {
NGX_RTMP_VIDEO_SORENSON_H263 = 2,
NGX_RTMP_VIDEO_SCREEN = 3,
NGX_RTMP_VIDEO_ON2_VP6 = 4,
NGX_RTMP_VIDEO_ON2_VP6_ALPHA = 5,
NGX_RTMP_VIDEO_H264 = 7
};
u_char * ngx_rtmp_get_audio_codec_name(ngx_uint_t id);
u_char * ngx_rtmp_get_video_codec_name(ngx_uint_t id);
#endif /* _NGX_RTMP_CODECS_H_INCLUDED_ */

View file

@ -5,7 +5,7 @@
#include "ngx_rtmp_live_module.h"
#include "ngx_rtmp_cmd_module.h"
#include "ngx_rtmp_codecs.h"
#include "ngx_rtmp_codec_module.h"
static ngx_rtmp_publish_pt next_publish;
@ -13,12 +13,6 @@ static ngx_rtmp_play_pt next_play;
static ngx_rtmp_delete_stream_pt next_delete_stream;
/* Chunk stream ids for output */
#define NGX_RTMP_LIVE_CSID_AUDIO 6
#define NGX_RTMP_LIVE_CSID_VIDEO 7
#define NGX_RTMP_LIVE_MSID 1
static ngx_int_t ngx_rtmp_live_postconfiguration(ngx_conf_t *cf);
static void * ngx_rtmp_live_create_app_conf(ngx_conf_t *cf);
static char * ngx_rtmp_live_merge_app_conf(ngx_conf_t *cf,
@ -268,10 +262,6 @@ ngx_rtmp_live_delete_stream(ngx_rtmp_session_t *s, ngx_rtmp_delete_stream_t *v)
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"live: delete empty stream '%s'", ctx->stream->name);
if (ctx->stream->avc_header) {
ngx_rtmp_free_shared_chain(cscf, ctx->stream->avc_header);
}
stream = ngx_rtmp_live_get_stream(s, ctx->stream->name, 0);
if (stream == NULL) {
return NGX_ERROR;
@ -292,14 +282,14 @@ ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_live_ctx_t *ctx, *pctx;
ngx_chain_t *out, *out_abs;
ngx_rtmp_codec_ctx_t *codec_ctx;
ngx_chain_t *out, *peer_out;
ngx_rtmp_core_srv_conf_t *cscf;
ngx_rtmp_live_app_conf_t *lacf;
ngx_rtmp_session_t *ss;
ngx_rtmp_header_t ch, lh;
ngx_uint_t prio, peer_prio;
ngx_uint_t peers, dropped_peers;
uint8_t flv_fmt;
lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module);
if (lacf == NULL) {
@ -358,28 +348,6 @@ ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
peers = 0;
dropped_peers = 0;
/* parse meta */
if (in->buf->last - in->buf->pos >= 1) {
flv_fmt = *in->buf->pos;
if (h->type == NGX_RTMP_MSG_AUDIO) {
ctx->stream->meta.audio_codec_id = (flv_fmt & 0xf0) >> 4;
} else {
ctx->stream->meta.video_codec_id = (flv_fmt & 0x0f);
if (ctx->stream->meta.video_codec_id == 7
&& in->buf->last - in->buf->pos >= 2
&& in->buf->pos[1] == 0)
{
/* AVC/H264 sequence header;
* save it for future */
if (ctx->stream->avc_header) {
ngx_rtmp_free_shared_chain(cscf, ctx->stream->avc_header);
}
ctx->stream->avc_header = out;
ngx_rtmp_acquire_shared_chain(out);
}
}
}
/* broadcast to all subscribers */
for (pctx = ctx->stream->ctx; pctx; pctx = pctx->next) {
if (pctx == ctx) {
@ -395,27 +363,38 @@ ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
"live: av: abs %s timestamp=%uD",
h->type == NGX_RTMP_MSG_VIDEO ? "video" : "audio",
ch.timestamp);
out_abs = ngx_rtmp_append_shared_bufs(cscf, NULL, in);
ngx_rtmp_prepare_message(s, &ch, NULL, out_abs);
peer_out = ngx_rtmp_append_shared_bufs(cscf, NULL, in);
ngx_rtmp_prepare_message(s, &ch, NULL, peer_out);
pctx->msg_mask |= (1 << h->type);
ngx_rtmp_send_message(ss, out_abs, prio);
ngx_rtmp_free_shared_chain(cscf, out_abs);
ngx_rtmp_send_message(ss, peer_out, prio);
ngx_rtmp_free_shared_chain(cscf, peer_out);
/* send AVC/H264 header */
if (ctx->stream->avc_header) {
/*TODO: make it absolute & send instead of ythe above frame */
ngx_rtmp_send_message(ss, ctx->stream->avc_header, prio);
codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
if (codec_ctx) {
peer_out = NULL;
if (h->type == NGX_RTMP_MSG_AUDIO) {
if (codec_ctx->aac_header) {
peer_out = codec_ctx->aac_header;
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, ss->connection->log,
0, "live: sending AAC header");
}
} else {
if (codec_ctx->avc_header) {
peer_out = codec_ctx->avc_header;
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, ss->connection->log,
0, "live: sending AVC/H264 header");
}
}
if (peer_out) {
ngx_rtmp_send_message(ss, peer_out, prio);
}
}
continue;
}
/* push buffered data */
peer_prio = prio;
/*
if (lacf->buflen && h->timestamp >= pctx->next_push) {
peer_prio = 0;
pctx->next_push = h->timestamp + lacf->buflen;
}*/
if (ngx_rtmp_send_message(ss, out, peer_prio) != NGX_OK) {
++pctx->dropped;
++dropped_peers;

View file

@ -8,6 +8,7 @@
#include "ngx_rtmp.h"
#include "ngx_rtmp_cmd_module.h"
#include "ngx_rtmp_bandwidth.h"
@ -15,6 +16,12 @@
#define NGX_RTMP_LIVE_PUBLISHING 0x01
/* Chunk stream ids for output */
#define NGX_RTMP_LIVE_CSID_AUDIO 6
#define NGX_RTMP_LIVE_CSID_VIDEO 7
#define NGX_RTMP_LIVE_MSID 1
typedef struct {
ngx_uint_t width;
ngx_uint_t height;
@ -46,7 +53,7 @@ struct ngx_rtmp_live_ctx_s {
struct ngx_rtmp_live_stream_s {
u_char name[256];
u_char name[NGX_RTMP_MAX_NAME];
ngx_rtmp_live_stream_t *next;
ngx_rtmp_live_ctx_t *ctx;
ngx_uint_t flags;
@ -54,7 +61,6 @@ struct ngx_rtmp_live_stream_s {
ngx_rtmp_bandwidth_t bw_out;
ngx_rtmp_live_meta_t meta;
ngx_msec_t epoch;
ngx_chain_t *avc_header;
};

View file

@ -8,6 +8,7 @@
#include "ngx_rtmp.h"
#include "ngx_rtmp_cmd_module.h"
#include "ngx_rtmp_netcall_module.h"
#include "ngx_rtmp_codec_module.h"
static ngx_rtmp_publish_pt next_publish;
@ -23,6 +24,8 @@ static ngx_int_t ngx_rtmp_record_postconfiguration(ngx_conf_t *cf);
static void * ngx_rtmp_record_create_app_conf(ngx_conf_t *cf);
static char * ngx_rtmp_record_merge_app_conf(ngx_conf_t *cf,
void *parent, void *child);
static ngx_int_t ngx_rtmp_record_write_frame(ngx_rtmp_session_t *s,
ngx_rtmp_header_t *h, ngx_chain_t *in);
typedef struct {
@ -231,7 +234,7 @@ ngx_rtmp_record_open(ngx_rtmp_session_t *s)
"record: failed to open file" " \"%s\" failed",
ctx->path);
}
return NGX_ERROR;
return NGX_OK;
}
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
@ -239,7 +242,7 @@ ngx_rtmp_record_open(ngx_rtmp_session_t *s)
if (ngx_rtmp_record_write_header(&ctx->file) != NGX_OK) {
ngx_rtmp_record_close(s);
return NGX_ERROR;
return NGX_OK;
}
return NGX_OK;
@ -418,66 +421,20 @@ ngx_rtmp_record_delete_stream(ngx_rtmp_session_t *s,
static ngx_int_t
ngx_rtmp_record_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_rtmp_record_write_frame(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_record_ctx_t *ctx;
ngx_rtmp_record_app_conf_t *racf;
u_char hdr[11], *p, *ph;
uint32_t timestamp, tag_size;
ngx_time_t next;
ngx_rtmp_record_ctx_t *ctx;
ngx_rtmp_record_app_conf_t *racf;
racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_record_module);
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);
if (racf == NULL || ctx == NULL || racf->flags & NGX_RTMP_RECORD_OFF) {
return NGX_OK;
}
if (ctx->file.fd == NGX_INVALID_FILE && racf->interval
&& (ctx->last.sec || ctx->last.msec))
{
next = ctx->last;
next.msec += racf->interval;
next.sec += (next.msec / 1000);
next.msec %= 1000;
if (ngx_cached_time->sec > next.sec
|| (ngx_cached_time->sec == next.sec
&& ngx_cached_time->msec > next.msec))
{
if (ngx_rtmp_record_open(s) != NGX_OK) {
ngx_log_error(NGX_LOG_CRIT, s->connection->log, 0,
"record: '%s' failed", ctx->path);
}
}
}
if (ctx->file.fd == NGX_INVALID_FILE) {
return NGX_OK;
}
/* filter frames */
if (h->type == NGX_RTMP_MSG_AUDIO &&
(racf->flags & NGX_RTMP_RECORD_AUDIO) == 0)
{
return NGX_OK;
}
if (h->type == NGX_RTMP_MSG_VIDEO &&
(racf->flags & NGX_RTMP_RECORD_VIDEO) == 0 &&
((racf->flags & NGX_RTMP_RECORD_KEYFRAMES) == 0
|| ngx_rtmp_get_video_frame_type(in) != NGX_RTMP_VIDEO_KEY_FRAME))
{
return NGX_OK;
}
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"record: av: mlen=%uD", h->mlen);
if (ctx->file.offset == 0) {
ctx->epoch = h->timestamp;
}
timestamp = h->timestamp - ctx->epoch;
/* write tag header */
@ -554,6 +511,113 @@ ngx_rtmp_record_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
}
static size_t
ngx_rtmp_record_get_chain_mlen(ngx_chain_t *in)
{
size_t ret;
for (ret = 0; in; in = in->next) {
ret += (in->buf->last - in->buf->pos);
}
return ret;
}
static ngx_int_t
ngx_rtmp_record_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h,
ngx_chain_t *in)
{
ngx_rtmp_record_ctx_t *ctx;
ngx_rtmp_record_app_conf_t *racf;
ngx_time_t next;
ngx_rtmp_header_t ch;
ngx_rtmp_codec_ctx_t *codec_ctx;
racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_record_module);
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module);
if (racf == NULL || ctx == NULL || racf->flags & NGX_RTMP_RECORD_OFF) {
return NGX_OK;
}
if (ctx->file.fd == NGX_INVALID_FILE && racf->interval
&& (ctx->last.sec || ctx->last.msec))
{
next = ctx->last;
next.msec += racf->interval;
next.sec += (next.msec / 1000);
next.msec %= 1000;
if (ngx_cached_time->sec > next.sec
|| (ngx_cached_time->sec == next.sec
&& ngx_cached_time->msec > next.msec))
{
if (ngx_rtmp_record_open(s) != NGX_OK) {
ngx_log_error(NGX_LOG_CRIT, s->connection->log, 0,
"record: '%s' failed", ctx->path);
}
}
}
if (ctx->file.fd == NGX_INVALID_FILE) {
return NGX_OK;
}
/* filter frames */
if (h->type == NGX_RTMP_MSG_AUDIO &&
(racf->flags & NGX_RTMP_RECORD_AUDIO) == 0)
{
return NGX_OK;
}
if (h->type == NGX_RTMP_MSG_VIDEO &&
(racf->flags & NGX_RTMP_RECORD_VIDEO) == 0 &&
((racf->flags & NGX_RTMP_RECORD_KEYFRAMES) == 0
|| ngx_rtmp_get_video_frame_type(in) != NGX_RTMP_VIDEO_KEY_FRAME))
{
return NGX_OK;
}
if (ctx->file.offset == 0) {
ctx->epoch = h->timestamp;
codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
if (codec_ctx == NULL) {
return NGX_OK;
}
if (codec_ctx) {
ch = *h;
if (codec_ctx->aac_header) {
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"record: writing AAC header");
ch.type = NGX_RTMP_MSG_AUDIO;
ch.mlen = ngx_rtmp_record_get_chain_mlen(codec_ctx->aac_header);
if (ngx_rtmp_record_write_frame(s, &ch, codec_ctx->aac_header)
!= NGX_OK)
{
return NGX_OK;
}
}
if (codec_ctx->avc_header) {
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"record: writing AVC header");
ch.type = NGX_RTMP_MSG_VIDEO;
ch.mlen = ngx_rtmp_record_get_chain_mlen(codec_ctx->avc_header);
if (ngx_rtmp_record_write_frame(s, &ch, codec_ctx->avc_header)
!= NGX_OK)
{
return NGX_OK;
}
}
}
}
return ngx_rtmp_record_write_frame(s, h, in);
}
static char *
ngx_rtmp_notify_on_record_done(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{

View file

@ -8,7 +8,7 @@
#include "ngx_rtmp.h"
#include "ngx_rtmp_live_module.h"
#include "ngx_rtmp_codecs.h"
#include "ngx_rtmp_codec_module.h"
static ngx_int_t ngx_rtmp_stat_postconfiguration(ngx_conf_t *cf);