mirror of
https://github.com/zotanmew/nginx-rtmp-module.git
synced 2024-06-29 00:18:58 +02:00
video & audio working
This commit is contained in:
parent
6caee7cb88
commit
c18fd3aad4
|
@ -31,6 +31,7 @@ typedef struct {
|
|||
ngx_uint_t opened;
|
||||
ngx_uint_t mdat_size;
|
||||
ngx_uint_t sample_count;
|
||||
ngx_uint_t sample_mask;
|
||||
ngx_fd_t fd;
|
||||
char type;
|
||||
uint32_t earliest_pres_time;
|
||||
|
@ -170,7 +171,6 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s)
|
|||
ngx_fd_t fd;
|
||||
ngx_str_t playlist, playlist_bak;
|
||||
ngx_rtmp_dash_ctx_t *ctx;
|
||||
ngx_rtmp_live_ctx_t *live_ctx;
|
||||
ngx_rtmp_codec_ctx_t *codec_ctx;
|
||||
ngx_rtmp_dash_app_conf_t *dacf;
|
||||
|
||||
|
@ -179,11 +179,8 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s)
|
|||
dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module);
|
||||
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
|
||||
codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
|
||||
live_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module);
|
||||
|
||||
if (dacf == NULL || ctx == NULL || codec_ctx == NULL ||
|
||||
live_ctx == NULL || live_ctx->stream == NULL)
|
||||
{
|
||||
if (dacf == NULL || ctx == NULL || codec_ctx == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
@ -228,9 +225,9 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s)
|
|||
" frameRate=\"%ui\"\n" \
|
||||
" sar=\"1:1\"\n" \
|
||||
" startWithSAP=\"1\"\n" \
|
||||
" bandwidth=\"%ui\">\n" \
|
||||
" bandwidth=\"0\">\n" \
|
||||
" <SegmentTemplate\n" \
|
||||
" presentationTimeOffset=\"%ui\"\n" \
|
||||
" presentationTimeOffset=\"0\"\n" \
|
||||
" timescale=\"1000\"\n" \
|
||||
" duration=\"%ui\"\n" \
|
||||
" media=\"%V-$Number$.m4v\"\n" \
|
||||
|
@ -253,10 +250,10 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s)
|
|||
" codecs=\"mp4a.%s\"\n" \
|
||||
" audioSamplingRate=\"%ui\"\n" \
|
||||
" startWithSAP=\"1\"\n" \
|
||||
" bandwidth=\"130685\">\n" \
|
||||
" bandwidth=\"0\">\n" \
|
||||
" <SegmentTemplate\n" \
|
||||
" presentationTimeOffset=\"%ui\"\n" \
|
||||
" timescale=\"%ui\"\n" \
|
||||
" presentationTimeOffset=\"0\"\n" \
|
||||
" timescale=\"1000\"\n" \
|
||||
" duration=\"%ui\"\n" \
|
||||
" media=\"%V-$Number$.m4a\"\n" \
|
||||
" startNumber=\"0\"\n" \
|
||||
|
@ -281,8 +278,6 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s)
|
|||
codec_ctx->width,
|
||||
codec_ctx->height,
|
||||
codec_ctx->frame_rate,
|
||||
(ngx_uint_t) (live_ctx->stream->bw_in.bandwidth * 8),
|
||||
(ngx_uint_t) 0,//ctx->video.earliest_pres_time,
|
||||
(ngx_uint_t) dacf->fraglen,
|
||||
&ctx->name,
|
||||
&ctx->name);
|
||||
|
@ -294,11 +289,7 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s)
|
|||
codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC ?
|
||||
"40.2" : "6b",
|
||||
codec_ctx->sample_rate,
|
||||
(ngx_uint_t) (ctx->audio.earliest_pres_time *
|
||||
(float) codec_ctx->sample_rate / 1000),
|
||||
codec_ctx->sample_rate,
|
||||
(ngx_uint_t) (dacf->fraglen * codec_ctx->sample_rate
|
||||
/ 1000),
|
||||
(ngx_uint_t) dacf->fraglen,
|
||||
&ctx->name,
|
||||
&ctx->name);
|
||||
n = ngx_write_fd(fd, buffer, p - buffer);
|
||||
|
@ -372,6 +363,7 @@ ngx_rtmp_dash_write_init_segments(ngx_rtmp_session_t *s)
|
|||
metadata.audio = 0;
|
||||
metadata.video = 1;
|
||||
|
||||
/*TODO: buffer control*/
|
||||
ngx_rtmp_mp4_write_ftyp(&b, NGX_RTMP_MP4_FILETYPE_INIT, &metadata);
|
||||
ngx_rtmp_mp4_write_moov(s, &b, &metadata);
|
||||
|
||||
|
@ -401,6 +393,7 @@ ngx_rtmp_dash_write_init_segments(ngx_rtmp_session_t *s)
|
|||
metadata.video = 0;
|
||||
metadata.audio = 1;
|
||||
|
||||
/*TODO: buffer control*/
|
||||
ngx_rtmp_mp4_write_ftyp(&b, NGX_RTMP_MP4_FILETYPE_INIT, &metadata);
|
||||
ngx_rtmp_mp4_write_moov(s, &b, &metadata);
|
||||
|
||||
|
@ -417,8 +410,7 @@ ngx_rtmp_dash_write_init_segments(ngx_rtmp_session_t *s)
|
|||
|
||||
|
||||
static void
|
||||
ngx_rtmp_dash_close_fragment(ngx_rtmp_session_t *s, ngx_rtmp_dash_track_t *t,
|
||||
ngx_uint_t sample_rate)
|
||||
ngx_rtmp_dash_close_fragment(ngx_rtmp_session_t *s, ngx_rtmp_dash_track_t *t)
|
||||
{
|
||||
u_char *pos, *pos1;
|
||||
size_t left;
|
||||
|
@ -451,13 +443,12 @@ ngx_rtmp_dash_close_fragment(ngx_rtmp_session_t *s, ngx_rtmp_dash_track_t *t,
|
|||
"dash: fragment earliest pts: %uD", t->earliest_pres_time);
|
||||
|
||||
ngx_rtmp_mp4_write_moof(&b, t->earliest_pres_time, t->sample_count,
|
||||
t->samples, t->id, sample_rate);
|
||||
t->samples, t->sample_mask, t->id);
|
||||
pos1 = b.last;
|
||||
b.last = pos;
|
||||
|
||||
ngx_rtmp_mp4_write_sidx(s, &b, t->mdat_size + 8 + (pos1 - (pos + 44)),
|
||||
t->earliest_pres_time, t->latest_pres_time,
|
||||
sample_rate);
|
||||
ngx_rtmp_mp4_write_sidx(&b, t->mdat_size + 8 + (pos1 - (pos + 44)),
|
||||
t->earliest_pres_time, t->latest_pres_time);
|
||||
b.last = pos1;
|
||||
ngx_rtmp_mp4_write_mdat(&b, t->mdat_size + 8);
|
||||
|
||||
|
@ -519,20 +510,18 @@ static ngx_int_t
|
|||
ngx_rtmp_dash_close_fragments(ngx_rtmp_session_t *s)
|
||||
{
|
||||
ngx_rtmp_dash_ctx_t *ctx;
|
||||
ngx_rtmp_codec_ctx_t *codec_ctx;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||
"dash: close fragments");
|
||||
|
||||
ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
|
||||
codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);
|
||||
|
||||
if (!ctx->opened) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
ngx_rtmp_dash_close_fragment(s, &ctx->video, 0);
|
||||
ngx_rtmp_dash_close_fragment(s, &ctx->audio, codec_ctx->sample_rate);
|
||||
ngx_rtmp_dash_close_fragment(s, &ctx->video);
|
||||
ngx_rtmp_dash_close_fragment(s, &ctx->audio);
|
||||
|
||||
ngx_rtmp_dash_write_playlist(s);
|
||||
|
||||
|
@ -574,6 +563,16 @@ ngx_rtmp_dash_open_fragment(ngx_rtmp_session_t *s, ngx_rtmp_dash_track_t *t,
|
|||
t->mdat_size = 0;
|
||||
t->opened = 1;
|
||||
|
||||
if (type == 'v') {
|
||||
t->sample_mask = NGX_RTMP_MP4_SAMPLE_SIZE|
|
||||
NGX_RTMP_MP4_SAMPLE_DURATION|
|
||||
NGX_RTMP_MP4_SAMPLE_DELAY|
|
||||
NGX_RTMP_MP4_SAMPLE_KEY;
|
||||
} else {
|
||||
t->sample_mask = NGX_RTMP_MP4_SAMPLE_SIZE|
|
||||
NGX_RTMP_MP4_SAMPLE_DURATION;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
@ -774,7 +773,7 @@ ngx_rtmp_dash_update_fragments(ngx_rtmp_session_t *s, ngx_int_t boundary,
|
|||
|
||||
static ngx_int_t
|
||||
ngx_rtmp_dash_append(ngx_rtmp_session_t *s, ngx_chain_t *in,
|
||||
ngx_rtmp_dash_track_t *t, ngx_int_t boundary, uint32_t timestamp)
|
||||
ngx_rtmp_dash_track_t *t, ngx_int_t key, uint32_t timestamp)
|
||||
{
|
||||
u_char *p;
|
||||
size_t size, bsize;
|
||||
|
@ -798,23 +797,18 @@ ngx_rtmp_dash_append(ngx_rtmp_session_t *s, ngx_chain_t *in,
|
|||
size += bsize;
|
||||
}
|
||||
|
||||
t->latest_pres_time = timestamp;
|
||||
|
||||
if (t->sample_count > 0) {
|
||||
t->samples[t->sample_count - 1].duration = timestamp -
|
||||
t->samples[t->sample_count - 1].timestamp;
|
||||
}
|
||||
|
||||
if (!ctx->opened) {
|
||||
ngx_rtmp_dash_open_fragments(s);
|
||||
}
|
||||
|
||||
ngx_rtmp_dash_update_fragments(s, boundary, timestamp);
|
||||
ngx_rtmp_dash_update_fragments(s, key, timestamp);
|
||||
|
||||
if (t->sample_count == 0) {
|
||||
t->earliest_pres_time = timestamp;
|
||||
}
|
||||
|
||||
t->latest_pres_time = timestamp;
|
||||
|
||||
if (t->sample_count < NGX_RTMP_DASH_MAX_SAMPLES) {
|
||||
|
||||
if (ngx_write_fd(t->fd, buffer, size) == NGX_ERROR) {
|
||||
|
@ -827,7 +821,12 @@ ngx_rtmp_dash_append(ngx_rtmp_session_t *s, ngx_chain_t *in,
|
|||
t->samples[t->sample_count].size = (uint32_t) size;
|
||||
t->samples[t->sample_count].duration = 0;
|
||||
t->samples[t->sample_count].timestamp = timestamp;
|
||||
t->samples[t->sample_count].key = (boundary ? 1 : 0);
|
||||
t->samples[t->sample_count].key = (key ? 1 : 0);
|
||||
|
||||
if (t->sample_count > 0) {
|
||||
t->samples[t->sample_count - 1].duration = timestamp -
|
||||
t->samples[t->sample_count - 1].timestamp;
|
||||
}
|
||||
|
||||
t->sample_count++;
|
||||
t->mdat_size += (ngx_uint_t) size;
|
||||
|
|
|
@ -303,7 +303,7 @@ ngx_rtmp_mp4_write_tkhd(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t *metadata)
|
|||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_rtmp_mp4_write_mdhd(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t *metadata)
|
||||
ngx_rtmp_mp4_write_mdhd(ngx_buf_t *b)
|
||||
{
|
||||
u_char *pos;
|
||||
|
||||
|
@ -314,15 +314,26 @@ ngx_rtmp_mp4_write_mdhd(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t *metadata)
|
|||
|
||||
b->last = ngx_cpymem(b->last, "mdhd", sizeof("mdhd") - 1);
|
||||
|
||||
ngx_rtmp_mp4_field_32(b, 0); /* version */
|
||||
ngx_rtmp_mp4_field_32(b, 0); /* creation time */
|
||||
ngx_rtmp_mp4_field_32(b, 0); /* modification time */
|
||||
/* version */
|
||||
ngx_rtmp_mp4_field_32(b, 0);
|
||||
|
||||
/* creation time */
|
||||
ngx_rtmp_mp4_field_32(b, 0);
|
||||
|
||||
/* modification time */
|
||||
ngx_rtmp_mp4_field_32(b, 0);
|
||||
|
||||
/* time scale*/
|
||||
ngx_rtmp_mp4_field_32(b, metadata->audio == 1 ? metadata->sample_rate :
|
||||
NGX_RTMP_MP4_TIMESCALE);
|
||||
ngx_rtmp_mp4_field_32(b, 0); /* duration */
|
||||
ngx_rtmp_mp4_field_16(b, 0x15C7); /* language */
|
||||
ngx_rtmp_mp4_field_16(b, 0); /* reserved */
|
||||
ngx_rtmp_mp4_field_32(b, NGX_RTMP_MP4_TIMESCALE);
|
||||
|
||||
/* duration */
|
||||
ngx_rtmp_mp4_field_32(b, 0);
|
||||
|
||||
/* lanuguage */
|
||||
ngx_rtmp_mp4_field_16(b, 0x15C7);
|
||||
|
||||
/* reserved */
|
||||
ngx_rtmp_mp4_field_16(b, 0);
|
||||
|
||||
ngx_rtmp_mp4_update_box_size(b, pos);
|
||||
|
||||
|
@ -824,7 +835,7 @@ ngx_rtmp_mp4_write_mdia(ngx_rtmp_session_t *s, ngx_buf_t *b,
|
|||
|
||||
b->last = ngx_cpymem(b->last, "mdia", sizeof("mdia") - 1);
|
||||
|
||||
ngx_rtmp_mp4_write_mdhd(b, metadata);
|
||||
ngx_rtmp_mp4_write_mdhd(b);
|
||||
ngx_rtmp_mp4_write_hdlr(b, metadata);
|
||||
ngx_rtmp_mp4_write_minf(s, b, metadata);
|
||||
|
||||
|
@ -859,15 +870,6 @@ static ngx_int_t
|
|||
ngx_rtmp_mp4_write_mvex(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t *metadata)
|
||||
{
|
||||
u_char *pos;
|
||||
uint32_t sample_dur;
|
||||
|
||||
if (metadata->video == 1) {
|
||||
sample_dur = metadata->frame_rate > 0 ? NGX_RTMP_MP4_TIMESCALE /
|
||||
metadata->frame_rate : NGX_RTMP_MP4_TIMESCALE;
|
||||
}
|
||||
else {
|
||||
sample_dur = metadata->audio_codec == NGX_RTMP_AUDIO_AAC ? 1024 : 1152;
|
||||
}
|
||||
|
||||
pos = b->last;
|
||||
|
||||
|
@ -885,17 +887,28 @@ ngx_rtmp_mp4_write_mvex(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t *metadata)
|
|||
ngx_rtmp_mp4_field_32(b, 0); /* version & flags */
|
||||
ngx_rtmp_mp4_field_32(b, 0x000D8D2A); /* frag duration */
|
||||
#endif
|
||||
|
||||
ngx_rtmp_mp4_field_32(b, 0x20);
|
||||
|
||||
b->last = ngx_cpymem(b->last, "trex", sizeof("trex") - 1);
|
||||
|
||||
ngx_rtmp_mp4_field_32(b, 0); /* version & flags */
|
||||
ngx_rtmp_mp4_field_32(b, 1); /* track id */
|
||||
ngx_rtmp_mp4_field_32(b, 1); /* default sample description index */
|
||||
ngx_rtmp_mp4_field_32(b, sample_dur); /* default sample duration */
|
||||
ngx_rtmp_mp4_field_32(b, 0); /* default sample size */
|
||||
/* default sample flags */
|
||||
ngx_rtmp_mp4_field_32(b, metadata->audio == 1 ? 0 : 0x00010000);
|
||||
/* version & flags */
|
||||
ngx_rtmp_mp4_field_32(b, 0);
|
||||
|
||||
/* track id */
|
||||
ngx_rtmp_mp4_field_32(b, 1);
|
||||
|
||||
/* default sample description index */
|
||||
ngx_rtmp_mp4_field_32(b, 1);
|
||||
|
||||
/* default sample duration */
|
||||
ngx_rtmp_mp4_field_32(b, 0);
|
||||
|
||||
/* default sample size, 1024 for AAC */
|
||||
ngx_rtmp_mp4_field_32(b, 1024);
|
||||
|
||||
/* default sample flags, key on */
|
||||
ngx_rtmp_mp4_field_32(b, 0);
|
||||
|
||||
ngx_rtmp_mp4_update_box_size(b, pos);
|
||||
|
||||
|
@ -927,7 +940,7 @@ ngx_rtmp_mp4_write_moov(ngx_rtmp_session_t *s, ngx_buf_t *b,
|
|||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_rtmp_mp4_write_tfhd(ngx_buf_t *b, ngx_uint_t sample_rate)
|
||||
ngx_rtmp_mp4_write_tfhd(ngx_buf_t *b)
|
||||
{
|
||||
u_char *pos;
|
||||
|
||||
|
@ -939,11 +952,10 @@ ngx_rtmp_mp4_write_tfhd(ngx_buf_t *b, ngx_uint_t sample_rate)
|
|||
b->last = ngx_cpymem(b->last, "tfhd", sizeof("tfhd")-1);
|
||||
|
||||
/* version & flags */
|
||||
ngx_rtmp_mp4_field_32(b, sample_rate > 0 ? 0x00020020 : 0x00020000);
|
||||
ngx_rtmp_mp4_field_32(b, 1); /* track id */
|
||||
if (sample_rate > 0) {
|
||||
ngx_rtmp_mp4_field_32(b, 0x02000000);
|
||||
}
|
||||
ngx_rtmp_mp4_field_32(b, 0x00020000);
|
||||
|
||||
/* track id */
|
||||
ngx_rtmp_mp4_field_32(b, 1);
|
||||
|
||||
ngx_rtmp_mp4_update_box_size(b, pos);
|
||||
|
||||
|
@ -952,18 +964,9 @@ ngx_rtmp_mp4_write_tfhd(ngx_buf_t *b, ngx_uint_t sample_rate)
|
|||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_rtmp_mp4_write_tfdt(ngx_buf_t *b, ngx_uint_t earliest_pres_time,
|
||||
ngx_uint_t sample_rate)
|
||||
ngx_rtmp_mp4_write_tfdt(ngx_buf_t *b, uint32_t earliest_pres_time)
|
||||
{
|
||||
u_char *pos;
|
||||
float multiplier;
|
||||
|
||||
if (sample_rate > 0) {
|
||||
multiplier = (float)sample_rate/(float)NGX_RTMP_MP4_TIMESCALE;
|
||||
}
|
||||
else {
|
||||
multiplier = 1;
|
||||
}
|
||||
|
||||
pos = b->last;
|
||||
|
||||
|
@ -972,9 +975,9 @@ ngx_rtmp_mp4_write_tfdt(ngx_buf_t *b, ngx_uint_t earliest_pres_time,
|
|||
|
||||
b->last = ngx_cpymem(b->last, "tfdt", sizeof("tfdt") - 1);
|
||||
|
||||
ngx_rtmp_mp4_field_32(b, 0x00000000); /* version == 1 aka 64 bit integer */
|
||||
/* earliest presentation time */
|
||||
ngx_rtmp_mp4_field_32(b, (uint32_t)((float)earliest_pres_time*multiplier));
|
||||
/* version == 1 aka 64 bit integer */
|
||||
ngx_rtmp_mp4_field_32(b, 0x00000000);
|
||||
ngx_rtmp_mp4_field_32(b, earliest_pres_time);
|
||||
|
||||
ngx_rtmp_mp4_update_box_size(b, pos);
|
||||
|
||||
|
@ -984,29 +987,66 @@ ngx_rtmp_mp4_write_tfdt(ngx_buf_t *b, ngx_uint_t earliest_pres_time,
|
|||
|
||||
static ngx_int_t
|
||||
ngx_rtmp_mp4_write_trun(ngx_buf_t *b, uint32_t sample_count,
|
||||
ngx_rtmp_mp4_sample_t *samples, u_char *moof_pos)
|
||||
ngx_rtmp_mp4_sample_t *samples, ngx_uint_t sample_mask, u_char *moof_pos)
|
||||
{
|
||||
u_char *pos;
|
||||
uint32_t i, offset;
|
||||
uint32_t i, offset, nitems, flags;
|
||||
|
||||
pos = b->last;
|
||||
|
||||
offset = (pos - moof_pos) + 20 + (sample_count * 4 * 4) + 8;
|
||||
nitems = 0;
|
||||
|
||||
/* data offset present */
|
||||
flags = 0x01;
|
||||
|
||||
if (sample_mask & NGX_RTMP_MP4_SAMPLE_DURATION) {
|
||||
nitems++;
|
||||
flags |= 0x000100;
|
||||
}
|
||||
|
||||
if (sample_mask & NGX_RTMP_MP4_SAMPLE_SIZE) {
|
||||
nitems++;
|
||||
flags |= 0x000200;
|
||||
}
|
||||
|
||||
if (sample_mask & NGX_RTMP_MP4_SAMPLE_KEY) {
|
||||
nitems++;
|
||||
flags |= 0x000400;
|
||||
}
|
||||
|
||||
if (sample_mask & NGX_RTMP_MP4_SAMPLE_DELAY) {
|
||||
nitems++;
|
||||
flags |= 0x000800;
|
||||
}
|
||||
|
||||
offset = (pos - moof_pos) + 20 + (sample_count * nitems * 4) + 8;
|
||||
|
||||
/* box size placeholder */
|
||||
ngx_rtmp_mp4_field_32(b, 0);
|
||||
|
||||
b->last = ngx_cpymem(b->last, "trun", sizeof("trun") - 1);
|
||||
|
||||
ngx_rtmp_mp4_field_32(b, 0x00000f01);
|
||||
ngx_rtmp_mp4_field_32(b, flags);
|
||||
ngx_rtmp_mp4_field_32(b, sample_count);
|
||||
ngx_rtmp_mp4_field_32(b, offset);
|
||||
|
||||
for (i = 0; i < sample_count; i++) {
|
||||
ngx_rtmp_mp4_field_32(b, samples[i].duration);
|
||||
ngx_rtmp_mp4_field_32(b, samples[i].size);
|
||||
ngx_rtmp_mp4_field_32(b, samples[i].key ? 0x00000000 : 0x00010000);
|
||||
ngx_rtmp_mp4_field_32(b, samples[i].delay);
|
||||
for (i = 0; i < sample_count; i++, samples++) {
|
||||
|
||||
if (sample_mask & NGX_RTMP_MP4_SAMPLE_DURATION) {
|
||||
ngx_rtmp_mp4_field_32(b, samples->duration);
|
||||
}
|
||||
|
||||
if (sample_mask & NGX_RTMP_MP4_SAMPLE_SIZE) {
|
||||
ngx_rtmp_mp4_field_32(b, samples->size);
|
||||
}
|
||||
|
||||
if (sample_mask & NGX_RTMP_MP4_SAMPLE_KEY) {
|
||||
ngx_rtmp_mp4_field_32(b, samples->key ? 0x00000000 : 0x00010000);
|
||||
}
|
||||
|
||||
if (sample_mask & NGX_RTMP_MP4_SAMPLE_DELAY) {
|
||||
ngx_rtmp_mp4_field_32(b, samples->delay);
|
||||
}
|
||||
}
|
||||
|
||||
ngx_rtmp_mp4_update_box_size(b, pos);
|
||||
|
@ -1016,9 +1056,9 @@ ngx_rtmp_mp4_write_trun(ngx_buf_t *b, uint32_t sample_count,
|
|||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_rtmp_mp4_write_traf(ngx_buf_t *b, ngx_uint_t earliest_pres_time,
|
||||
uint32_t sample_count, ngx_rtmp_mp4_sample_t *samples, u_char *moof_pos,
|
||||
ngx_uint_t sample_rate)
|
||||
ngx_rtmp_mp4_write_traf(ngx_buf_t *b, uint32_t earliest_pres_time,
|
||||
uint32_t sample_count, ngx_rtmp_mp4_sample_t *samples,
|
||||
ngx_uint_t sample_mask, u_char *moof_pos)
|
||||
{
|
||||
u_char *pos;
|
||||
|
||||
|
@ -1029,9 +1069,9 @@ ngx_rtmp_mp4_write_traf(ngx_buf_t *b, ngx_uint_t earliest_pres_time,
|
|||
|
||||
b->last = ngx_cpymem(b->last, "traf", sizeof("traf") - 1);
|
||||
|
||||
ngx_rtmp_mp4_write_tfhd(b, sample_rate);
|
||||
ngx_rtmp_mp4_write_tfdt(b, earliest_pres_time, sample_rate);
|
||||
ngx_rtmp_mp4_write_trun(b, sample_count, samples, moof_pos);
|
||||
ngx_rtmp_mp4_write_tfhd(b);
|
||||
ngx_rtmp_mp4_write_tfdt(b, earliest_pres_time);
|
||||
ngx_rtmp_mp4_write_trun(b, sample_count, samples, sample_mask, moof_pos);
|
||||
|
||||
ngx_rtmp_mp4_update_box_size(b, pos);
|
||||
|
||||
|
@ -1051,8 +1091,11 @@ ngx_rtmp_mp4_write_mfhd(ngx_buf_t *b, uint32_t index)
|
|||
|
||||
b->last = ngx_cpymem(b->last, "mfhd", sizeof("mfhd")-1);
|
||||
|
||||
ngx_rtmp_mp4_field_32(b, 0); /* don't know what this is */
|
||||
ngx_rtmp_mp4_field_32(b, index); /* fragment index. */
|
||||
/* don't know what this is */
|
||||
ngx_rtmp_mp4_field_32(b, 0);
|
||||
|
||||
/* fragment index. */
|
||||
ngx_rtmp_mp4_field_32(b, index);
|
||||
|
||||
ngx_rtmp_mp4_update_box_size(b, pos);
|
||||
|
||||
|
@ -1061,27 +1104,13 @@ ngx_rtmp_mp4_write_mfhd(ngx_buf_t *b, uint32_t index)
|
|||
|
||||
|
||||
ngx_int_t
|
||||
ngx_rtmp_mp4_write_sidx(ngx_rtmp_session_t *s, ngx_buf_t *b,
|
||||
ngx_uint_t reference_size, ngx_uint_t earliest_pres_time,
|
||||
ngx_uint_t latest_pres_time, ngx_uint_t sample_rate)
|
||||
ngx_rtmp_mp4_write_sidx(ngx_buf_t *b, ngx_uint_t reference_size,
|
||||
uint32_t earliest_pres_time, uint32_t latest_pres_time)
|
||||
{
|
||||
u_char *pos;
|
||||
uint32_t ept, dur;
|
||||
uint32_t duration;
|
||||
|
||||
if (sample_rate > 0) {
|
||||
ept = (uint32_t)((float)earliest_pres_time*((float)sample_rate /
|
||||
(float)NGX_RTMP_MP4_TIMESCALE));
|
||||
dur = (uint32_t)((float)(latest_pres_time-earliest_pres_time) *
|
||||
((float)sample_rate/(float)NGX_RTMP_MP4_TIMESCALE));
|
||||
}
|
||||
else {
|
||||
ept = earliest_pres_time;
|
||||
dur = (latest_pres_time-earliest_pres_time);
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||||
"dash: buffered dash range start: %uL, duration: %uL",
|
||||
ept, dur);
|
||||
duration = latest_pres_time - earliest_pres_time;
|
||||
pos = b->last;
|
||||
|
||||
/* box size placeholder */
|
||||
|
@ -1089,21 +1118,38 @@ ngx_rtmp_mp4_write_sidx(ngx_rtmp_session_t *s, ngx_buf_t *b,
|
|||
|
||||
b->last = ngx_cpymem(b->last, "sidx", sizeof("sidx") - 1);
|
||||
|
||||
ngx_rtmp_mp4_field_32(b, 0); /* version */
|
||||
ngx_rtmp_mp4_field_32(b, 1); /* reference id */
|
||||
/* version */
|
||||
ngx_rtmp_mp4_field_32(b, 0);
|
||||
|
||||
/* reference id */
|
||||
ngx_rtmp_mp4_field_32(b, 1);
|
||||
|
||||
/* timescale */
|
||||
ngx_rtmp_mp4_field_32(b, sample_rate > 0 ? sample_rate :
|
||||
NGX_RTMP_MP4_TIMESCALE);
|
||||
ngx_rtmp_mp4_field_32(b, ept); /* earliest presentation time */
|
||||
ngx_rtmp_mp4_field_32(b, 0); /* first offset */
|
||||
ngx_rtmp_mp4_field_16(b, 0); /* reserved */
|
||||
ngx_rtmp_mp4_field_16(b, 1); /* reference count (=1) */
|
||||
ngx_rtmp_mp4_field_32(b, NGX_RTMP_MP4_TIMESCALE);
|
||||
|
||||
/* earliest presentation time */
|
||||
ngx_rtmp_mp4_field_32(b, earliest_pres_time);
|
||||
|
||||
/* first offset */
|
||||
ngx_rtmp_mp4_field_32(b, duration); /*TODO*/
|
||||
|
||||
/* reserved */
|
||||
ngx_rtmp_mp4_field_16(b, 0);
|
||||
|
||||
/* reference count = 1 */
|
||||
ngx_rtmp_mp4_field_16(b, 1);
|
||||
|
||||
/* 1st bit is reference type, the rest is reference size */
|
||||
ngx_rtmp_mp4_field_32(b, reference_size);
|
||||
ngx_rtmp_mp4_field_32(b, dur); /* subsegment duration */
|
||||
|
||||
/* subsegment duration */
|
||||
ngx_rtmp_mp4_field_32(b, duration);
|
||||
|
||||
/* first bit is startsWithSAP (=1), next 3 bits are SAP type (=001) */
|
||||
ngx_rtmp_mp4_field_8(b, 0x90);
|
||||
ngx_rtmp_mp4_field_24(b, 0); /* SAP delta time */
|
||||
|
||||
/* SAP delta time */
|
||||
ngx_rtmp_mp4_field_24(b, 0);
|
||||
|
||||
ngx_rtmp_mp4_update_box_size(b, pos);
|
||||
|
||||
|
@ -1112,9 +1158,9 @@ ngx_rtmp_mp4_write_sidx(ngx_rtmp_session_t *s, ngx_buf_t *b,
|
|||
|
||||
|
||||
ngx_int_t
|
||||
ngx_rtmp_mp4_write_moof(ngx_buf_t *b, ngx_uint_t earliest_pres_time,
|
||||
uint32_t sample_count, ngx_rtmp_mp4_sample_t *samples, uint32_t index,
|
||||
ngx_uint_t sample_rate)
|
||||
ngx_rtmp_mp4_write_moof(ngx_buf_t *b, uint32_t earliest_pres_time,
|
||||
uint32_t sample_count, ngx_rtmp_mp4_sample_t *samples,
|
||||
ngx_uint_t sample_mask, uint32_t index)
|
||||
{
|
||||
u_char *pos;
|
||||
|
||||
|
@ -1127,7 +1173,7 @@ ngx_rtmp_mp4_write_moof(ngx_buf_t *b, ngx_uint_t earliest_pres_time,
|
|||
|
||||
ngx_rtmp_mp4_write_mfhd(b, index);
|
||||
ngx_rtmp_mp4_write_traf(b, earliest_pres_time, sample_count, samples,
|
||||
pos, sample_rate);
|
||||
sample_mask, pos);
|
||||
|
||||
ngx_rtmp_mp4_update_box_size(b, pos);
|
||||
|
||||
|
|
|
@ -9,6 +9,12 @@
|
|||
#include <ngx_rtmp.h>
|
||||
|
||||
|
||||
#define NGX_RTMP_MP4_SAMPLE_SIZE 0x01
|
||||
#define NGX_RTMP_MP4_SAMPLE_DURATION 0x02
|
||||
#define NGX_RTMP_MP4_SAMPLE_DELAY 0x04
|
||||
#define NGX_RTMP_MP4_SAMPLE_KEY 0x08
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t size;
|
||||
uint32_t duration;
|
||||
|
@ -39,12 +45,12 @@ ngx_int_t ngx_rtmp_mp4_write_ftyp(ngx_buf_t *b, int type,
|
|||
ngx_rtmp_mp4_metadata_t *metadata);
|
||||
ngx_int_t ngx_rtmp_mp4_write_moov(ngx_rtmp_session_t *s, ngx_buf_t *b,
|
||||
ngx_rtmp_mp4_metadata_t *metadata);
|
||||
ngx_int_t ngx_rtmp_mp4_write_moof(ngx_buf_t *b, ngx_uint_t earliest_pres_time,
|
||||
uint32_t sample_count, ngx_rtmp_mp4_sample_t *samples, uint32_t index,
|
||||
ngx_uint_t sample_rate);
|
||||
ngx_int_t ngx_rtmp_mp4_write_sidx(ngx_rtmp_session_t *s, ngx_buf_t *b,
|
||||
ngx_uint_t reference_size, ngx_uint_t earliest_pres_time,
|
||||
ngx_uint_t latest_pres_time, ngx_uint_t sample_rate);
|
||||
ngx_int_t ngx_rtmp_mp4_write_moof(ngx_buf_t *b, uint32_t earliest_pres_time,
|
||||
uint32_t sample_count, ngx_rtmp_mp4_sample_t *samples,
|
||||
ngx_uint_t sample_mask, uint32_t index);
|
||||
ngx_int_t ngx_rtmp_mp4_write_sidx(ngx_buf_t *b,
|
||||
ngx_uint_t reference_size, uint32_t earliest_pres_time,
|
||||
uint32_t latest_pres_time);
|
||||
ngx_uint_t ngx_rtmp_mp4_write_mdat(ngx_buf_t *b, ngx_uint_t size);
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue