From 055228cc8af3d637544a8c70de89ed22dcceb9cb Mon Sep 17 00:00:00 2001 From: Stephen Basile Date: Tue, 8 Oct 2013 16:15:44 -0400 Subject: [PATCH] style changes --- hls/ngx_rtmp_dash_module.c | 202 ++++++++++++++++++++++++------------- hls/ngx_rtmp_mp4.c | 183 ++++++++++++++++++++++++--------- hls/ngx_rtmp_mp4.h | 37 +++++-- 3 files changed, 294 insertions(+), 128 deletions(-) diff --git a/hls/ngx_rtmp_dash_module.c b/hls/ngx_rtmp_dash_module.c index 31f6a44..210f456 100644 --- a/hls/ngx_rtmp_dash_module.c +++ b/hls/ngx_rtmp_dash_module.c @@ -1,3 +1,5 @@ + + #include #include #include @@ -5,21 +7,25 @@ #include "ngx_rtmp_live_module.h" #include "ngx_rtmp_mp4.h" + static ngx_rtmp_publish_pt next_publish; static ngx_rtmp_close_stream_pt next_close_stream; static ngx_rtmp_stream_begin_pt next_stream_begin; static ngx_rtmp_stream_eof_pt next_stream_eof; + static ngx_int_t ngx_rtmp_dash_postconfiguration(ngx_conf_t *cf); static void * ngx_rtmp_dash_create_app_conf(ngx_conf_t *cf); static char * ngx_rtmp_dash_merge_app_conf(ngx_conf_t *cf, void *parent, void *child); + #define NGX_RTMP_DASH_BUFSIZE (1024*1024) #define NGX_RTMP_DASH_DIR_ACCESS 0744 #define NGX_RTMP_DASH_MAX_SIZE (800*1024) #define NGX_RTMP_DASH_MAX_SAMPLES 512 + typedef struct { ngx_uint_t video_earliest_pres_time; ngx_uint_t video_latest_pres_time; @@ -29,6 +35,7 @@ typedef struct { uint32_t id; } ngx_rtmp_dash_frag_t; + typedef struct { ngx_str_t playlist; ngx_str_t playlist_bak; @@ -60,11 +67,13 @@ typedef struct { ngx_str_t audio_fragment; } ngx_rtmp_dash_ctx_t; + typedef struct { ngx_str_t path; ngx_msec_t playlen; } ngx_rtmp_dash_cleanup_t; + typedef struct { ngx_flag_t dash; ngx_msec_t fraglen; @@ -75,6 +84,7 @@ typedef struct { ngx_path_t *slot; } ngx_rtmp_dash_app_conf_t; + static ngx_command_t ngx_rtmp_dash_commands[] = { { ngx_string("dash"), @@ -105,7 +115,6 @@ static ngx_command_t ngx_rtmp_dash_commands[] = { offsetof(ngx_rtmp_dash_app_conf_t, playlen), NULL }, - { ngx_string("dash_cleanup"), NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, ngx_conf_set_flag_slot, @@ -116,6 +125,7 @@ static ngx_command_t ngx_rtmp_dash_commands[] = { ngx_null_command }; + static ngx_rtmp_module_t ngx_rtmp_dash_module_ctx = { NULL, /* preconfiguration */ ngx_rtmp_dash_postconfiguration, /* postconfiguration */ @@ -146,6 +156,7 @@ ngx_module_t ngx_rtmp_dash_module = { NGX_MODULE_V1_PADDING }; + static ngx_rtmp_dash_frag_t * ngx_rtmp_dash_get_frag(ngx_rtmp_session_t *s, ngx_int_t n) { @@ -158,6 +169,7 @@ ngx_rtmp_dash_get_frag(ngx_rtmp_session_t *s, ngx_int_t n) return &ctx->frags[(ctx->frag + n) % (hacf->winfrags * 2 + 1)]; } + static ngx_int_t ngx_rtmp_dash_rename_file(u_char *src, u_char *dst) { @@ -170,6 +182,7 @@ ngx_rtmp_dash_rename_file(u_char *src, u_char *dst) #endif } + static ngx_int_t ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s) { @@ -207,31 +220,46 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s) return NGX_ERROR; } -#define NGX_RTMP_DASH_MANIFEST_HEADER \ - "\n"\ - "\n"\ +#define NGX_RTMP_DASH_MANIFEST_HEADER \ + "\n" \ + "\n" \ " \n" -#define NGX_RTMP_DASH_MANIFEST_VIDEO \ - " \n"\ - " \n"\ - " \n"\ - " \n"\ +#define NGX_RTMP_DASH_MANIFEST_VIDEO \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ " \n" -#define NGX_RTMP_DASH_MANIFEST_AUDIO \ +#define NGX_RTMP_DASH_MANIFEST_AUDIO \ " \n"\ - " \n"\ - " \n"\ - " \n"\ - " \n"\ + " \n" \ + " \n" \ + " \n" \ + " \n" \ " \n" -#define NGX_RTMP_DASH_MANIFEST_FOOTER \ - " \n"\ +#define NGX_RTMP_DASH_MANIFEST_FOOTER \ + " \n" \ "\n" f = ngx_rtmp_dash_get_frag(s, hacf->winfrags/2); - audio_dur = f->id > 0 ? (uint32_t)(codec_ctx->sample_rate*((float)(f->video_latest_pres_time/f->id)/1000.0)) : - (uint32_t)(codec_ctx->sample_rate*(hacf->fraglen/1000)); + audio_dur = f->id > 0 ? (uint32_t)(codec_ctx->sample_rate * + ((float)(f->video_latest_pres_time/f->id)/1000.0)) : + (uint32_t)(codec_ctx->sample_rate*(hacf->fraglen/1000)); p = ngx_snprintf(buffer, sizeof(buffer), NGX_RTMP_DASH_MANIFEST_HEADER, &ctx->start_time); @@ -239,28 +267,30 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s) if (ctx->video) { p = ngx_snprintf(buffer, sizeof(buffer), NGX_RTMP_DASH_MANIFEST_VIDEO, - codec_ctx->width, - codec_ctx->height, - codec_ctx->frame_rate, - codec_ctx->width, - codec_ctx->height, - codec_ctx->frame_rate, - (uint32_t)(live_ctx->stream->bw_in.bandwidth*8), - f->video_earliest_pres_time, - f->id > 0 ? (uint32_t)(f->video_latest_pres_time/f->id) : hacf->fraglen, - &ctx->name, - &ctx->name); + codec_ctx->width, + codec_ctx->height, + codec_ctx->frame_rate, + codec_ctx->width, + codec_ctx->height, + codec_ctx->frame_rate, + (uint32_t)(live_ctx->stream->bw_in.bandwidth*8), + f->video_earliest_pres_time, + f->id > 0 ? (uint32_t)(f->video_latest_pres_time / + f->id) : hacf->fraglen, + &ctx->name, + &ctx->name); n = ngx_write_fd(fd, buffer, p - buffer); } if (ctx->audio) { p = ngx_snprintf(buffer, sizeof(buffer), NGX_RTMP_DASH_MANIFEST_AUDIO, - codec_ctx->sample_rate, - (uint32_t)(f->audio_earliest_pres_time*((float)codec_ctx->sample_rate/1000.0)), - codec_ctx->sample_rate, - audio_dur, - &ctx->name, - &ctx->name); + codec_ctx->sample_rate, + (uint32_t)(f->audio_earliest_pres_time * + ((float)codec_ctx->sample_rate/1000.0)), + codec_ctx->sample_rate, + audio_dur, + &ctx->name, + &ctx->name); n = ngx_write_fd(fd, buffer, p - buffer); } @@ -286,6 +316,7 @@ ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s) return NGX_OK; } + static ngx_int_t ngx_rtmp_dash_write_init_segments(ngx_rtmp_session_t *s) { @@ -308,7 +339,7 @@ ngx_rtmp_dash_write_init_segments(ngx_rtmp_session_t *s) ngx_snprintf(path, sizeof(path), "%Vinit-video.dash",&ctx->stream); file.fd = ngx_open_file(path, NGX_FILE_RDWR, - NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); + NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); if (file.fd == NGX_INVALID_FILE) { @@ -351,7 +382,7 @@ ngx_rtmp_dash_write_init_segments(ngx_rtmp_session_t *s) ngx_snprintf(path, sizeof(path), "%Vinit-audio.dash",&ctx->stream); file.fd = ngx_open_file(path, NGX_FILE_RDWR, - NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); + NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); if (file.fd == NGX_INVALID_FILE) { @@ -379,6 +410,7 @@ ngx_rtmp_dash_write_init_segments(ngx_rtmp_session_t *s) return NGX_OK; } + static ngx_int_t ngx_rtmp_dash_rewrite_segments(ngx_rtmp_session_t *s) { @@ -416,12 +448,14 @@ ngx_rtmp_dash_rewrite_segments(ngx_rtmp_session_t *s) ngx_rtmp_mp4_write_ftyp(b, NGX_RTMP_MP4_FILETYPE_SEG, metadata); pos = b->last; b->last += 44; /* leave room for sidx */ - ngx_rtmp_mp4_write_moof(b, f->video_earliest_pres_time, ctx->video_sample_count, - ctx->video_sample_sizes, (ctx->nfrags+ctx->frag),0); + ngx_rtmp_mp4_write_moof(b, f->video_earliest_pres_time, + ctx->video_sample_count, ctx->video_sample_sizes, + (ctx->nfrags+ctx->frag),0); pos1 = b->last; b->last = pos; - ngx_rtmp_mp4_write_sidx(s, b, ctx->video_mdat_size+8+(pos1-(pos+44)), f->video_earliest_pres_time, - f->video_latest_pres_time,0); + ngx_rtmp_mp4_write_sidx(s, b, ctx->video_mdat_size+8+(pos1-(pos+44)), + f->video_earliest_pres_time, + f->video_latest_pres_time,0); b->last = pos1; ngx_rtmp_mp4_write_mdat(b, ctx->video_mdat_size+8); @@ -433,7 +467,7 @@ ngx_rtmp_dash_rewrite_segments(ngx_rtmp_session_t *s) ngx_memzero(&file, sizeof(file)); file.log = s->connection->log; file.fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR, - NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); + NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); if (file.fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, @@ -448,11 +482,13 @@ ngx_rtmp_dash_rewrite_segments(ngx_rtmp_session_t *s) do { file_b.pos = file_b.last = file_b.start; if ((ssize_t)(written + sizeof(buffer)) > size) { - ngx_read_file(&ctx->video_file, file_b.start, size-written, ctx->video_file.offset); + ngx_read_file(&ctx->video_file, file_b.start, size-written, + ctx->video_file.offset); file_b.last += size-written; } else { - ngx_read_file(&ctx->video_file, file_b.start, sizeof(buffer), ctx->video_file.offset); + ngx_read_file(&ctx->video_file, file_b.start, sizeof(buffer), + ctx->video_file.offset); file_b.last += sizeof(buffer); } write_size = ngx_rtmp_mp4_write_data(s, &file, &file_b); @@ -467,7 +503,8 @@ ngx_rtmp_dash_rewrite_segments(ngx_rtmp_session_t *s) rc = ngx_rtmp_dash_rename_file(ctx->stream.data, ctx->video_fragment.data); if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, - "dash: rename failed: '%s'->'%s'",ctx->stream.data, ctx->video_fragment.data); + "dash: rename failed: '%s'->'%s'",ctx->stream.data, + ctx->video_fragment.data); return NGX_ERROR; } @@ -479,12 +516,14 @@ ngx_rtmp_dash_rewrite_segments(ngx_rtmp_session_t *s) ngx_rtmp_mp4_write_ftyp(b, NGX_RTMP_MP4_FILETYPE_SEG, metadata); pos = b->last; b->last += 44; /* leave room for sidx */ - ngx_rtmp_mp4_write_moof(b, f->audio_earliest_pres_time, ctx->audio_sample_count, - ctx->audio_sample_sizes, (ctx->nfrags+ctx->frag), codec_ctx->sample_rate); + ngx_rtmp_mp4_write_moof(b, f->audio_earliest_pres_time, + ctx->audio_sample_count, ctx->audio_sample_sizes, + (ctx->nfrags+ctx->frag), codec_ctx->sample_rate); pos1 = b->last; b->last = pos; - ngx_rtmp_mp4_write_sidx(s, b, ctx->audio_mdat_size+8+(pos1-(pos+44)), f->audio_earliest_pres_time, - f->audio_latest_pres_time, codec_ctx->sample_rate); + ngx_rtmp_mp4_write_sidx(s, b, ctx->audio_mdat_size+8+(pos1-(pos+44)), + f->audio_earliest_pres_time, + f->audio_latest_pres_time, codec_ctx->sample_rate); b->last = pos1; ngx_rtmp_mp4_write_mdat(b, ctx->audio_mdat_size+8); @@ -496,7 +535,7 @@ ngx_rtmp_dash_rewrite_segments(ngx_rtmp_session_t *s) ngx_memzero(&file, sizeof(file)); file.log = s->connection->log; file.fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR, - NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); + NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); if (file.fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, @@ -511,11 +550,13 @@ ngx_rtmp_dash_rewrite_segments(ngx_rtmp_session_t *s) do { file_b.pos = file_b.last = file_b.start; if ((ssize_t)(written + sizeof(buffer)) > size) { - ngx_read_file(&ctx->audio_file, file_b.start, size-written, ctx->audio_file.offset); + ngx_read_file(&ctx->audio_file, file_b.start, size-written, + ctx->audio_file.offset); file_b.last += size-written; } else { - ngx_read_file(&ctx->audio_file, file_b.start, sizeof(buffer), ctx->audio_file.offset); + ngx_read_file(&ctx->audio_file, file_b.start, sizeof(buffer), + ctx->audio_file.offset); file_b.last += sizeof(buffer); } write_size = ngx_rtmp_mp4_write_data(s, &file, &file_b); @@ -530,13 +571,15 @@ ngx_rtmp_dash_rewrite_segments(ngx_rtmp_session_t *s) rc = ngx_rtmp_dash_rename_file(ctx->stream.data, ctx->audio_fragment.data); if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, - "dash: rename failed: '%s'->'%s'",ctx->stream.data, ctx->audio_fragment.data); + "dash: rename failed: '%s'->'%s'",ctx->stream.data, + ctx->audio_fragment.data); return NGX_ERROR; } return NGX_OK; } + static ngx_int_t ngx_rtmp_dash_close_fragments(ngx_rtmp_session_t *s) { @@ -585,7 +628,8 @@ ngx_rtmp_dash_open_fragments(ngx_rtmp_session_t *s) ctx->audio_file.log = s->connection->log; *ngx_sprintf(ctx->stream.data + ctx->stream.len, "%uL.m4v", f->id) = 0; - *ngx_sprintf(ctx->video_fragment.data + ctx->stream.len, "%uL.m4v", f->id) = 0; + *ngx_sprintf(ctx->video_fragment.data + ctx->stream.len, "%uL.m4v", + f->id) = 0; ngx_str_set(&ctx->video_file.name, "dash-v"); ctx->video_file.fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR, @@ -597,10 +641,12 @@ ngx_rtmp_dash_open_fragments(ngx_rtmp_session_t *s) } *ngx_sprintf(ctx->stream.data + ctx->stream.len, "%uL.m4a", f->id) = 0; - *ngx_sprintf(ctx->audio_fragment.data + ctx->stream.len, "%uL.m4a", f->id) = 0; + *ngx_sprintf(ctx->audio_fragment.data + ctx->stream.len, "%uL.m4a", + f->id) = 0; ngx_str_set(&ctx->audio_file.name, "dash-a"); ctx->audio_file.fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR, - NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); + NGX_FILE_TRUNCATE, + NGX_FILE_DEFAULT_ACCESS); if (ctx->audio_file.fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno, @@ -621,6 +667,7 @@ ngx_rtmp_dash_open_fragments(ngx_rtmp_session_t *s) return NGX_OK; } + static ngx_int_t ngx_rtmp_dash_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) { @@ -709,9 +756,11 @@ ngx_rtmp_dash_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) ctx->audio_fragment.len + NGX_INT64_LEN + sizeof(".m4a")); - ngx_memcpy(ctx->video_fragment.data, ctx->playlist.data, ctx->video_fragment.len - 1); + ngx_memcpy(ctx->video_fragment.data, ctx->playlist.data, + ctx->video_fragment.len - 1); ctx->video_fragment.data[ctx->video_fragment.len - 1] = '-'; - ngx_memcpy(ctx->audio_fragment.data, ctx->playlist.data, ctx->audio_fragment.len - 1); + ngx_memcpy(ctx->audio_fragment.data, ctx->playlist.data, + ctx->audio_fragment.len - 1); ctx->audio_fragment.data[ctx->audio_fragment.len - 1] = '-'; /* playlist path */ @@ -748,6 +797,7 @@ next: return next_publish(s, v); } + static ngx_int_t ngx_rtmp_dash_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v) { @@ -771,8 +821,10 @@ next: return next_close_stream(s, v); } + static void -ngx_rtmp_dash_update_fragments(ngx_rtmp_session_t *s, ngx_int_t boundary, uint32_t ts) +ngx_rtmp_dash_update_fragments(ngx_rtmp_session_t *s, ngx_int_t boundary, + uint32_t ts) { ngx_rtmp_dash_ctx_t *ctx; ngx_rtmp_dash_app_conf_t *hacf; @@ -785,8 +837,10 @@ ngx_rtmp_dash_update_fragments(ngx_rtmp_session_t *s, ngx_int_t boundary, uint32 f = ngx_rtmp_dash_get_frag(s, ctx->nfrags); - duration = ctx->video ? (f->video_latest_pres_time-f->video_earliest_pres_time) : - (f->audio_latest_pres_time-f->audio_earliest_pres_time); + duration = ctx->video ? (f->video_latest_pres_time - + f->video_earliest_pres_time) : + (f->audio_latest_pres_time - + f->audio_earliest_pres_time); if ((ctx->video) && ((int32_t)(hacf->fraglen - duration) > 150)) { boundary = 0; @@ -873,12 +927,14 @@ ngx_rtmp_dash_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, bsize = out.end - out.last; } if (*in->buf->pos == 0xAF) { /* rtmp frame header */ - if (*(in->buf->pos+1) == 0x00) { /* rtmp audio frame number--skip 0 */ + /* rtmp audio frame number--skip 0 */ + if (*(in->buf->pos+1) == 0x00) { break; } else { if (bsize > 2) { - in->buf->pos += 2; /* skip two bytes of audio frame header */ + /* skip two bytes of audio frame header */ + in->buf->pos += 2; } } } @@ -901,8 +957,10 @@ ngx_rtmp_dash_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ctx->audio_sample_count += 1; if ((ctx->audio_sample_count <= NGX_RTMP_DASH_MAX_SAMPLES)) { - ctx->audio_sample_sizes[ctx->audio_sample_count] = ngx_rtmp_mp4_write_data(s, &ctx->audio_file, &out); - ctx->audio_mdat_size += ctx->audio_sample_sizes[ctx->audio_sample_count]; + ctx->audio_sample_sizes[ctx->audio_sample_count] = + ngx_rtmp_mp4_write_data(s, &ctx->audio_file, &out); + ctx->audio_mdat_size += + ctx->audio_sample_sizes[ctx->audio_sample_count]; } else { ctx->audio_sample_count = NGX_RTMP_DASH_MAX_SAMPLES; @@ -912,6 +970,7 @@ ngx_rtmp_dash_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, return NGX_OK; } + static ngx_int_t ngx_rtmp_dash_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_chain_t *in) @@ -1000,8 +1059,10 @@ ngx_rtmp_dash_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ctx->video_sample_count += 1; if (ctx->video_sample_count <= NGX_RTMP_DASH_MAX_SAMPLES) { - ctx->video_sample_sizes[ctx->video_sample_count] = ngx_rtmp_mp4_write_data(s, &ctx->video_file, &out); - ctx->video_mdat_size += ctx->video_sample_sizes[ctx->video_sample_count]; + ctx->video_sample_sizes[ctx->video_sample_count] = + ngx_rtmp_mp4_write_data(s, &ctx->video_file, &out); + ctx->video_mdat_size += + ctx->video_sample_sizes[ctx->video_sample_count]; } else { ctx->video_sample_count = NGX_RTMP_DASH_MAX_SAMPLES; @@ -1010,6 +1071,7 @@ ngx_rtmp_dash_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, return NGX_OK; } + static void ngx_rtmp_dash_discontinue(ngx_rtmp_session_t *s) { @@ -1028,6 +1090,7 @@ ngx_rtmp_dash_discontinue(ngx_rtmp_session_t *s) } } + static ngx_int_t ngx_rtmp_dash_stream_begin(ngx_rtmp_session_t *s, ngx_rtmp_stream_begin_t *v) { @@ -1045,6 +1108,7 @@ ngx_rtmp_dash_stream_eof(ngx_rtmp_session_t *s, ngx_rtmp_stream_eof_t *v) return next_stream_eof(s, v); } + static ngx_int_t ngx_rtmp_dash_cleanup_dir(ngx_str_t *ppath, ngx_msec_t playlen) { @@ -1180,6 +1244,7 @@ ngx_rtmp_dash_cleanup_dir(ngx_str_t *ppath, ngx_msec_t playlen) } } + static time_t ngx_rtmp_dash_cleanup(void *data) { @@ -1190,6 +1255,7 @@ ngx_rtmp_dash_cleanup(void *data) return cleanup->playlen / 500; } + static void * ngx_rtmp_dash_create_app_conf(ngx_conf_t *cf) { @@ -1288,4 +1354,4 @@ ngx_rtmp_dash_postconfiguration(ngx_conf_t *cf) ngx_rtmp_stream_eof = ngx_rtmp_dash_stream_eof; return NGX_OK; -} \ No newline at end of file +} diff --git a/hls/ngx_rtmp_mp4.c b/hls/ngx_rtmp_mp4.c index 076e99c..e2a8c25 100644 --- a/hls/ngx_rtmp_mp4.c +++ b/hls/ngx_rtmp_mp4.c @@ -1,13 +1,16 @@ + #include #include #include "ngx_rtmp_mp4.h" #include + static u_char compressor_name[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + ngx_int_t ngx_rtmp_mp4_field_64(ngx_buf_t *b, uint64_t n) { @@ -27,6 +30,7 @@ ngx_rtmp_mp4_field_64(ngx_buf_t *b, uint64_t n) return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_field_32(ngx_buf_t *b, uint32_t n) { @@ -42,6 +46,7 @@ ngx_rtmp_mp4_field_32(ngx_buf_t *b, uint32_t n) return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_field_24(ngx_buf_t *b, uint32_t n) { @@ -56,6 +61,7 @@ ngx_rtmp_mp4_field_24(ngx_buf_t *b, uint32_t n) return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_field_16(ngx_buf_t *b, uint32_t n) { @@ -69,6 +75,7 @@ ngx_rtmp_mp4_field_16(ngx_buf_t *b, uint32_t n) return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_field_8(ngx_buf_t *b, unsigned int n) { @@ -81,11 +88,12 @@ ngx_rtmp_mp4_field_8(ngx_buf_t *b, unsigned int n) return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_put_descr(ngx_buf_t *b, int tag, unsigned int size) { //int i = 3; - /* initially stolen from ffmpeg, but most of it doesnt appear to be necessary */ + /* initially stolen from ffmpeg, but most of it isnt necessary */ ngx_rtmp_mp4_field_8(b, tag); //for (; i > 0; i--) { @@ -96,6 +104,7 @@ ngx_rtmp_mp4_put_descr(ngx_buf_t *b, int tag, unsigned int size) { return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_update_box_size(ngx_buf_t *b, u_char *pos) { @@ -111,13 +120,14 @@ ngx_rtmp_mp4_update_box_size(ngx_buf_t *b, u_char *pos) return NGX_OK; } + /* transformation matrix |a b u| |c d v| |tx ty w| */ ngx_int_t ngx_rtmp_mp4_write_matrix(ngx_buf_t *buf, int16_t a, int16_t b, int16_t c, - int16_t d, int16_t tx, int16_t ty) + int16_t d, int16_t tx, int16_t ty) { ngx_rtmp_mp4_field_32(buf, a << 16); /* 16.16 format */ ngx_rtmp_mp4_field_32(buf, b << 16); /* 16.16 format */ @@ -132,8 +142,10 @@ ngx_rtmp_mp4_write_matrix(ngx_buf_t *buf, int16_t a, int16_t b, int16_t c, return NGX_OK; } + ngx_int_t -ngx_rtmp_mp4_write_ftyp(ngx_buf_t *b, int type, ngx_rtmp_mp4_metadata_t metadata) +ngx_rtmp_mp4_write_ftyp(ngx_buf_t *b, int type, + ngx_rtmp_mp4_metadata_t metadata) { u_char *pos; @@ -147,7 +159,8 @@ ngx_rtmp_mp4_write_ftyp(ngx_buf_t *b, int type, ngx_rtmp_mp4_metadata_t metadata ngx_rtmp_mp4_field_32(b, 1); if (metadata.video == 1) { - b->last = ngx_cpymem(b->last, "avc1iso5dash", sizeof("avc1iso5dash")-1); + b->last = ngx_cpymem(b->last, "avc1iso5dash", + sizeof("avc1iso5dash")-1); } else { b->last = ngx_cpymem(b->last, "iso5dash", sizeof("iso5dash")-1); @@ -163,10 +176,11 @@ ngx_rtmp_mp4_write_ftyp(ngx_buf_t *b, int type, ngx_rtmp_mp4_metadata_t metadata } ngx_rtmp_mp4_update_box_size(b, pos); - + return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_write_mvhd(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) { @@ -184,8 +198,8 @@ ngx_rtmp_mp4_write_mvhd(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) ngx_rtmp_mp4_field_32(b, 0); /* modification time */ ngx_rtmp_mp4_field_32(b, NGX_RTMP_MP4_TIMESCALE); /* timescale */ ngx_rtmp_mp4_field_32(b, 0); /* duration */ - ngx_rtmp_mp4_field_32(b, NGX_RTMP_MP4_PREFERRED_RATE); /* preferred playback rate */ - ngx_rtmp_mp4_field_16(b, NGX_RTMP_MP4_PREFERRED_VOLUME); /* preferred volume rate */ + ngx_rtmp_mp4_field_32(b, NGX_RTMP_MP4_PREFERRED_RATE); /* playback rate */ + ngx_rtmp_mp4_field_16(b, NGX_RTMP_MP4_PREFERRED_VOLUME); /* volume rate */ ngx_rtmp_mp4_field_16(b, 0); /* reserved */ ngx_rtmp_mp4_field_32(b, 0); /* reserved */ ngx_rtmp_mp4_field_32(b, 0); /* reserved */ @@ -206,6 +220,7 @@ ngx_rtmp_mp4_write_mvhd(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_write_tkhd(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) { @@ -227,7 +242,8 @@ ngx_rtmp_mp4_write_tkhd(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) ngx_rtmp_mp4_field_32(b, 0); /* duration */ ngx_rtmp_mp4_field_32(b, 0); /* reserved */ ngx_rtmp_mp4_field_32(b, 0); /* reserved */ - ngx_rtmp_mp4_field_32(b, metadata.audio == 1 ? 0x00000001 : 0); /* 2 16s, layer and alternate group */ + /* 2 16s, layer and alternate group */ + ngx_rtmp_mp4_field_32(b, metadata.audio == 1 ? 0x00000001 : 0); ngx_rtmp_mp4_field_16(b, metadata.audio == 1 ? 0x0100 : 0); ngx_rtmp_mp4_field_16(b, 0); /* reserved */ @@ -247,6 +263,7 @@ ngx_rtmp_mp4_write_tkhd(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_write_mdhd(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) { @@ -262,7 +279,9 @@ ngx_rtmp_mp4_write_mdhd(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) 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 */ - ngx_rtmp_mp4_field_32(b, metadata.audio == 1 ? metadata.sample_rate : NGX_RTMP_MP4_TIMESCALE); /* time scale*/ + /* 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 */ @@ -272,6 +291,7 @@ ngx_rtmp_mp4_write_mdhd(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_write_hdlr(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) { @@ -287,10 +307,12 @@ ngx_rtmp_mp4_write_hdlr(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) ngx_rtmp_mp4_field_32(b, 0); /* version and flags */ ngx_rtmp_mp4_field_32(b, 0); /* pre defined (=0) */ if (metadata.video == 1) { - b->last = ngx_cpymem(b->last, "vide", sizeof("vide")-1); /* video handler */ + /* video handler */ + b->last = ngx_cpymem(b->last, "vide", sizeof("vide")-1); } else { - b->last = ngx_cpymem(b->last, "soun", sizeof("soun")-1); /* sound handler */ + /* sound handler */ + b->last = ngx_cpymem(b->last, "soun", sizeof("soun")-1); } ngx_rtmp_mp4_field_32(b, 0); /* reserved */ @@ -298,10 +320,12 @@ ngx_rtmp_mp4_write_hdlr(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) ngx_rtmp_mp4_field_32(b, 0); /* reserved */ if (metadata.video == 1) { - b->last = ngx_cpymem(b->last, "VideoHandler", sizeof("VideoHandler")); /* video handler string--NULL TERMINATED */ + /* video handler string--NULL TERMINATED */ + b->last = ngx_cpymem(b->last, "VideoHandler", sizeof("VideoHandler")); } else { - b->last = ngx_cpymem(b->last, "SoundHandler", sizeof("SoundHandler")); /* sound handler string--NULL TERMINATED */ + /* sound handler string--NULL TERMINATED */ + b->last = ngx_cpymem(b->last, "SoundHandler", sizeof("SoundHandler")); } ngx_rtmp_mp4_update_box_size(b, pos); @@ -309,6 +333,7 @@ ngx_rtmp_mp4_write_hdlr(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_write_vmhd(ngx_buf_t *b) { @@ -324,6 +349,7 @@ ngx_rtmp_mp4_write_vmhd(ngx_buf_t *b) return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_write_smhd(ngx_buf_t *b) { @@ -339,6 +365,7 @@ ngx_rtmp_mp4_write_smhd(ngx_buf_t *b) return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_write_dref(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) { @@ -364,6 +391,7 @@ ngx_rtmp_mp4_write_dref(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_write_dinf(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) { @@ -383,8 +411,10 @@ ngx_rtmp_mp4_write_dinf(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) return NGX_OK; } + ngx_int_t -ngx_rtmp_mp4_write_avcc(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) +ngx_rtmp_mp4_write_avcc(ngx_rtmp_session_t *s, ngx_buf_t *b, + ngx_rtmp_mp4_metadata_t metadata) { u_char *pos, *p; ngx_rtmp_codec_ctx_t *codec_ctx; @@ -427,8 +457,10 @@ ngx_rtmp_mp4_write_avcc(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metada return NGX_OK; } + ngx_int_t -ngx_rtmp_mp4_write_video(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) +ngx_rtmp_mp4_write_video(ngx_rtmp_session_t *s, ngx_buf_t *b, + ngx_rtmp_mp4_metadata_t metadata) { u_char *pos; @@ -473,10 +505,10 @@ ngx_rtmp_mp4_write_video(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metad return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_write_esds(ngx_rtmp_session_t *s, ngx_buf_t *b) { - /* SCREW THIS FUNCTION */ u_char *pos; ngx_rtmp_codec_ctx_t *codec_ctx; @@ -507,14 +539,17 @@ ngx_rtmp_mp4_write_esds(ngx_rtmp_session_t *s, ngx_buf_t *b) b->last = ngx_cpymem(b->last, "esds", sizeof("esds")-1); ngx_rtmp_mp4_field_32(b, 0); /* version */ - ngx_rtmp_mp4_put_descr(b, 0x03, 23+decoder_info); /* length of the rest of the box */ + /* length of the rest of the box */ + ngx_rtmp_mp4_put_descr(b, 0x03, 23+decoder_info); ngx_rtmp_mp4_field_16(b, 1); /* track id */ ngx_rtmp_mp4_field_8(b, 0x00); /* flags */ - ngx_rtmp_mp4_put_descr(b, 0x04, 15+decoder_info); /* length of the rest of the box */ + /* length of the rest of the box */ + ngx_rtmp_mp4_put_descr(b, 0x04, 15+decoder_info); ngx_rtmp_mp4_field_8(b, 0x40); /* codec id */ ngx_rtmp_mp4_field_8(b, 0x15); /* audio stream */ ngx_rtmp_mp4_field_24(b, 0); /* buffersize? */ - ngx_rtmp_mp4_field_32(b, 0x0001F151); /* bitrate TODO: should probably set it dynamically*/ + /* bitrate TODO: should probably set it dynamically*/ + ngx_rtmp_mp4_field_32(b, 0x0001F151); ngx_rtmp_mp4_field_32(b, 0x0001F14D); /* I really dont know */ if (aac) { @@ -530,8 +565,10 @@ ngx_rtmp_mp4_write_esds(ngx_rtmp_session_t *s, ngx_buf_t *b) return NGX_OK; } + ngx_int_t -ngx_rtmp_mp4_write_audio(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) +ngx_rtmp_mp4_write_audio(ngx_rtmp_session_t *s, ngx_buf_t *b, + ngx_rtmp_mp4_metadata_t metadata) { u_char *pos; @@ -564,8 +601,10 @@ ngx_rtmp_mp4_write_audio(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metad return NGX_OK; } + ngx_int_t -ngx_rtmp_mp4_write_stsd(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) +ngx_rtmp_mp4_write_stsd(ngx_rtmp_session_t *s, ngx_buf_t *b, + ngx_rtmp_mp4_metadata_t metadata) { u_char *pos; @@ -591,6 +630,7 @@ ngx_rtmp_mp4_write_stsd(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metada return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_write_stts(ngx_buf_t *b) { @@ -611,6 +651,7 @@ ngx_rtmp_mp4_write_stts(ngx_buf_t *b) return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_write_stsc(ngx_buf_t *b) { @@ -631,6 +672,7 @@ ngx_rtmp_mp4_write_stsc(ngx_buf_t *b) return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_write_stsz(ngx_buf_t *b) { @@ -652,6 +694,7 @@ ngx_rtmp_mp4_write_stsz(ngx_buf_t *b) return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_write_stco(ngx_buf_t *b) { @@ -672,8 +715,10 @@ ngx_rtmp_mp4_write_stco(ngx_buf_t *b) return NGX_OK; } + ngx_int_t -ngx_rtmp_mp4_write_stbl(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) +ngx_rtmp_mp4_write_stbl(ngx_rtmp_session_t *s, ngx_buf_t *b, + ngx_rtmp_mp4_metadata_t metadata) { u_char *pos; @@ -695,8 +740,10 @@ ngx_rtmp_mp4_write_stbl(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metada return NGX_OK; } + ngx_int_t -ngx_rtmp_mp4_write_minf(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) +ngx_rtmp_mp4_write_minf(ngx_rtmp_session_t *s, ngx_buf_t *b, + ngx_rtmp_mp4_metadata_t metadata) { u_char *pos; @@ -722,8 +769,10 @@ ngx_rtmp_mp4_write_minf(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metada return NGX_OK; } + ngx_int_t -ngx_rtmp_mp4_write_mdia(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) +ngx_rtmp_mp4_write_mdia(ngx_rtmp_session_t *s, ngx_buf_t *b, + ngx_rtmp_mp4_metadata_t metadata) { u_char *pos; @@ -744,7 +793,8 @@ ngx_rtmp_mp4_write_mdia(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metada } ngx_int_t -ngx_rtmp_mp4_write_trak(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) +ngx_rtmp_mp4_write_trak(ngx_rtmp_session_t *s, ngx_buf_t *b, + ngx_rtmp_mp4_metadata_t metadata) { u_char *pos; @@ -763,6 +813,7 @@ ngx_rtmp_mp4_write_trak(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metada return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_write_mvex(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) { @@ -770,7 +821,8 @@ ngx_rtmp_mp4_write_mvex(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) 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; + sample_dur = metadata.frame_rate > 0 ? NGX_RTMP_MP4_TIMESCALE / + metadata.frame_rate : NGX_RTMP_MP4_TIMESCALE; } else { sample_dur = 1024; @@ -801,15 +853,18 @@ ngx_rtmp_mp4_write_mvex(ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) 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 */ - ngx_rtmp_mp4_field_32(b, metadata.audio == 1 ? 0 : 0x00010000); /* default sample flags */ + /* default sample flags */ + ngx_rtmp_mp4_field_32(b, metadata.audio == 1 ? 0 : 0x00010000); ngx_rtmp_mp4_update_box_size(b, pos); return NGX_OK; } + ngx_int_t -ngx_rtmp_mp4_write_moov(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metadata_t metadata) +ngx_rtmp_mp4_write_moov(ngx_rtmp_session_t *s, ngx_buf_t *b, + ngx_rtmp_mp4_metadata_t metadata) { u_char *pos; @@ -829,6 +884,7 @@ ngx_rtmp_mp4_write_moov(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_rtmp_mp4_metada return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_write_tfhd(ngx_buf_t *b, ngx_uint_t sample_rate) { @@ -841,7 +897,8 @@ ngx_rtmp_mp4_write_tfhd(ngx_buf_t *b, ngx_uint_t sample_rate) b->last = ngx_cpymem(b->last, "tfhd", sizeof("tfhd")-1); - ngx_rtmp_mp4_field_32(b, sample_rate > 0 ? 0x00020020 : 0x00020000); /* version & flags */ + /* 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); @@ -852,8 +909,10 @@ ngx_rtmp_mp4_write_tfhd(ngx_buf_t *b, ngx_uint_t sample_rate) return NGX_OK; } + 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, ngx_uint_t earliest_pres_time, + ngx_uint_t sample_rate) { u_char *pos; float multiplier; @@ -873,16 +932,19 @@ ngx_rtmp_mp4_write_tfdt(ngx_buf_t *b, ngx_uint_t earliest_pres_time, ngx_uint_t b->last = ngx_cpymem(b->last, "tfdt", sizeof("tfdt")-1); ngx_rtmp_mp4_field_32(b, 0x00000000); /* version == 1 aka 64 bit integer */ - ngx_rtmp_mp4_field_32(b, (uint32_t)((float)earliest_pres_time*multiplier)); /* no idea */ + /* earliest presentation time */ + ngx_rtmp_mp4_field_32(b, (uint32_t)((float)earliest_pres_time*multiplier)); ngx_rtmp_mp4_update_box_size(b, pos); return NGX_OK; } + ngx_int_t -ngx_rtmp_mp4_write_trun(ngx_buf_t *b, uint32_t sample_count, uint32_t sample_sizes[128], - u_char *moof_pos, ngx_uint_t sample_rate) +ngx_rtmp_mp4_write_trun(ngx_buf_t *b, uint32_t sample_count, + uint32_t sample_sizes[128], u_char *moof_pos, + ngx_uint_t sample_rate) { u_char *pos; uint32_t i, offset; @@ -890,10 +952,12 @@ ngx_rtmp_mp4_write_trun(ngx_buf_t *b, uint32_t sample_count, uint32_t sample_siz pos = b->last; if (sample_rate > 0) { - offset = (pos-moof_pos) + 20 + (sample_count*4) + 8; /* moof stuff + trun stuff + sample entries + mdat header */ + /* moof stuff + trun stuff + sample entries + mdat header */ + offset = (pos-moof_pos) + 20 + (sample_count*4) + 8; } else { - offset = (pos-moof_pos) + 24 + (sample_count*4) + 8; /* moof stuff + trun stuff + sample entries + mdat header */ + /* moof stuff + trun stuff + sample entries + mdat header */ + offset = (pos-moof_pos) + 24 + (sample_count*4) + 8; } @@ -902,7 +966,8 @@ ngx_rtmp_mp4_write_trun(ngx_buf_t *b, uint32_t sample_count, uint32_t sample_siz b->last = ngx_cpymem(b->last, "trun", sizeof("trun")-1); - ngx_rtmp_mp4_field_32(b, sample_rate > 0 ? 0x00000201 : 0x00000205); /* version and flags */ + /* version and flags */ + ngx_rtmp_mp4_field_32(b, sample_rate > 0 ? 0x00000201 : 0x00000205); ngx_rtmp_mp4_field_32(b, sample_count); /* sample count */ ngx_rtmp_mp4_field_32(b, offset); /* data offset */ if (sample_rate == 0) { @@ -918,9 +983,11 @@ ngx_rtmp_mp4_write_trun(ngx_buf_t *b, uint32_t sample_count, uint32_t sample_siz return NGX_OK; } + ngx_int_t -ngx_rtmp_mp4_write_traf(ngx_buf_t *b, ngx_uint_t earliest_pres_time, uint32_t sample_count, uint32_t sample_sizes[128], - u_char *moof_pos, ngx_uint_t sample_rate) +ngx_rtmp_mp4_write_traf(ngx_buf_t *b, ngx_uint_t earliest_pres_time, + uint32_t sample_count, uint32_t sample_sizes[128], + u_char *moof_pos, ngx_uint_t sample_rate) { u_char *pos; @@ -933,13 +1000,15 @@ ngx_rtmp_mp4_write_traf(ngx_buf_t *b, ngx_uint_t earliest_pres_time, uint32_t sa 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, sample_sizes, moof_pos, sample_rate); + ngx_rtmp_mp4_write_trun(b, sample_count, sample_sizes, moof_pos, + sample_rate); ngx_rtmp_mp4_update_box_size(b, pos); return NGX_OK; } + ngx_int_t ngx_rtmp_mp4_write_mfhd(ngx_buf_t *b, uint32_t index) { @@ -960,16 +1029,21 @@ ngx_rtmp_mp4_write_mfhd(ngx_buf_t *b, uint32_t index) return NGX_OK; } + 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_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) { u_char *pos; uint32_t ept, dur; 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)); + 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; @@ -988,14 +1062,18 @@ ngx_rtmp_mp4_write_sidx(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_uint_t referenc ngx_rtmp_mp4_field_32(b, 0); /* version */ ngx_rtmp_mp4_field_32(b, 1); /* reference id */ - ngx_rtmp_mp4_field_32(b, sample_rate > 0 ? sample_rate : NGX_RTMP_MP4_TIMESCALE); /* timescale */ + /* 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, reference_size); /* 1st bit is reference type, the rest is reference size */ + /* 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 */ - ngx_rtmp_mp4_field_8(b, 0x90); /* first bit is startsWithSAP (=1), next 3 bits are SAP type (=001) */ + /* 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 */ ngx_rtmp_mp4_update_box_size(b, pos); @@ -1003,9 +1081,11 @@ ngx_rtmp_mp4_write_sidx(ngx_rtmp_session_t *s, ngx_buf_t *b, ngx_uint_t referenc return NGX_OK; } + ngx_int_t -ngx_rtmp_mp4_write_moof(ngx_buf_t *b, ngx_uint_t earliest_pres_time, uint32_t sample_count, - uint32_t sample_sizes[128], uint32_t index, ngx_uint_t sample_rate) +ngx_rtmp_mp4_write_moof(ngx_buf_t *b, ngx_uint_t earliest_pres_time, + uint32_t sample_count, uint32_t sample_sizes[128], + uint32_t index, ngx_uint_t sample_rate) { u_char *pos; @@ -1017,13 +1097,15 @@ ngx_rtmp_mp4_write_moof(ngx_buf_t *b, ngx_uint_t earliest_pres_time, uint32_t sa b->last = ngx_cpymem(b->last, "moof", sizeof("moof")-1); ngx_rtmp_mp4_write_mfhd(b, index); - ngx_rtmp_mp4_write_traf(b, earliest_pres_time, sample_count, sample_sizes, pos, sample_rate); + ngx_rtmp_mp4_write_traf(b, earliest_pres_time, sample_count, sample_sizes, + pos, sample_rate); ngx_rtmp_mp4_update_box_size(b, pos); return NGX_OK; } + ngx_uint_t ngx_rtmp_mp4_write_mdat(ngx_buf_t *b, ngx_uint_t size) { @@ -1034,6 +1116,7 @@ ngx_rtmp_mp4_write_mdat(ngx_buf_t *b, ngx_uint_t size) return NGX_OK; } + uint32_t ngx_rtmp_mp4_write_data(ngx_rtmp_session_t *s, ngx_file_t *file, ngx_buf_t *b) { @@ -1061,4 +1144,4 @@ ngx_rtmp_mp4_write_data(ngx_rtmp_session_t *s, ngx_file_t *file, ngx_buf_t *b) } return size; -} \ No newline at end of file +} diff --git a/hls/ngx_rtmp_mp4.h b/hls/ngx_rtmp_mp4.h index 0cd2b51..bfef725 100644 --- a/hls/ngx_rtmp_mp4.h +++ b/hls/ngx_rtmp_mp4.h @@ -1,4 +1,5 @@ + #ifndef _NGX_RTMP_MP4_H_INCLUDED_ #define _NGX_RTMP_MP4_H_INCLUDED_ @@ -7,6 +8,7 @@ #include #include + typedef struct { ngx_uint_t width; ngx_uint_t height; @@ -16,23 +18,38 @@ typedef struct { ngx_uint_t frame_rate; } ngx_rtmp_mp4_metadata_t; + enum { NGX_RTMP_MP4_FILETYPE_INIT = 0, NGX_RTMP_MP4_FILETYPE_SEG = 1 }; -#define NGX_RTMP_MP4_TIMESCALE 1000 /* divide all times by this value. this is the same resolution as RTMP so it is convenient */ -#define NGX_RTMP_MP4_PREFERRED_RATE 0x00010000 /* normal forward playback as defined by spec */ -#define NGX_RTMP_MP4_PREFERRED_VOLUME 0x0100 /* full volume as defined by spec */ -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, - uint32_t sample_sizes[128], 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); +/* divide all times by this value. this is the same resolution as RTMP so it +is convenient */ +#define NGX_RTMP_MP4_TIMESCALE 1000 +/* normal forward playback as defined by spec */ +#define NGX_RTMP_MP4_PREFERRED_RATE 0x00010000 +/* full volume as defined by spec */ +#define NGX_RTMP_MP4_PREFERRED_VOLUME 0x0100 + +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, + uint32_t sample_sizes[128], 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_uint_t ngx_rtmp_mp4_write_mdat(ngx_buf_t *b, ngx_uint_t size); -uint32_t ngx_rtmp_mp4_write_data(ngx_rtmp_session_t *s, ngx_file_t *file, ngx_buf_t *b); +uint32_t ngx_rtmp_mp4_write_data(ngx_rtmp_session_t *s, ngx_file_t *file, + ngx_buf_t *b); #endif /* _NGX_RTMP_MP4_H_INCLUDED_ */ \ No newline at end of file